How do you organize your code in a j2me project?

随声附和 提交于 2019-12-05 02:58:10

问题


Sorry if what I'm about to ask you is a silly question, but since I'm taking my first steps into j2me I have to do it. I know that you can have multiple screens in a single MIDlet, but that doesn't seem to be a good idea when you're going to have a considerable number of screens(more than 10) as it would end up in a complete mess. So here's the question(not sure if possible), how do you usually organize your code in a j2me project? Or do you put everything inside a single MIDlet or do you separate your code into different MIDlets, one per screen, as we usually do in web or desktop applications??

I also noticed that when a project have multiple MIDlets and you launch the emulator, you have the possibility to start each of them. If you can have different functionality in different MIDlets, being able to run any MIDlet without following a specific order,doesn't seem very convenient since a MIDlet might depend on the data that is read in a previous MIDlet.

Please if it is possible to separate different functionality into different MIDlets , do you think you could give a general idea of how to do it?? Which steps to take in general.

Thanks in advance.


回答1:


General rule: Don't try to get to complex in a single MIDlet :), something I rather like about java-me, i.e. do one thing well ...

The MIDlet corresponds to an application, since it is subjected to life cycle management.

In simple cases (i.e. in most cases) I let it implement the CommandListener interface, too, so in MVC terms it is the controller. The controller logic is implemented in the commandAction method (basically if then else on the combination command and screen).

The different screens like List and TextBox instances correspond to the views in MVC. Put those in separate *.java files. A screen could be tied to an object from your model (e.g an editor) so pass it to the screen in the MIDlet's commandAction method.

I have seen examples where the screens implement the commandListener, but to me that's mixing concepts and generally less maintainable ...

You are fairly free in your choice of implementing the model part, however you might want to look into the javax.microedition.rms package for persistence and there are persistent implementations for contacts and calendar entries ...

Let's say you have the following domain object class (DomainObject.java):

package mvc.midlet;

public class DomainObject {
    public String name = "";
    public String street = "";
    public String phone = "";
}

and you want an app to create up to 10 objects, with an overview screen (a list of object) and an editor for the oject.

Here is the code for the overview screen (Overview.java):

package mvc.midlet;

import javax.microedition.lcdui.List;

public class Overview extends List {

    public static Overview create(DomainObject[] data) {
        int i = 0;
        for(; i < data.length; i++) {
            if(data[i] == null) break;
        }
        String[] names = new String[i];
        for(int j = 0; j < i; j++) {
            names[j] = data[j].name;
        }
        return new Overview(names);
    }

    protected Overview(String names[]) {
        super("Overview", IMPLICIT, names, null);
    }

}

and here is the editor code (Editor.java):

package mvc.midlet;

import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.TextField;

public class Editor extends Form {

    public static Editor create(DomainObject object, boolean isNew) {
        return new Editor(object, isNew);
    }

    private final DomainObject object;
    public final boolean isNew;
    public DomainObject getObject() {
        return object;
    }

    private final TextField name;
    private final TextField street;
    private final TextField phone;

    protected Editor(DomainObject object, boolean isNew) {
        super("Edit");
        this.object = object;
        this.isNew = isNew;
        this.name = new TextField("Name", object.name, 10, TextField.INITIAL_CAPS_WORD);
        this.append(name);
        this.street = new TextField("Street", object.street, 10, TextField.INITIAL_CAPS_WORD);
        this.append(street);
        this.phone = new TextField("Phone", object.phone, 10, TextField.PHONENUMBER);
        this.append(phone);
    }

    public String getName() {
        return name.getString();
    }
    public String getStreet() {
        return street.getString();
    }
    public String getPhone() {
        return phone.getString();
    }
    public void saveValues() {
        object.name = getName();
        object.street = getStreet();
        object.phone = getPhone();
    }
}

And finally the MIDlet that controls it all (MvcMIDlet.java):

/**
 * 
 */
package mvc.midlet;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * @author cm
 *
 */
public class MvcMIDlet extends MIDlet implements CommandListener {

    private Command add = new Command("New", Command.SCREEN, 0x01);
    private Command edit= new Command("Edit", Command.SCREEN, 0x01);
    private Command exit= new Command("Exit", Command.EXIT, 0x01);
    private Command ok= new Command("OK", Command.OK, 0x01);

    DomainObject[] data = new DomainObject[10];
    DomainObject current = null;

    /**
     * Initialize some sample data
     */
    public MvcMIDlet() {
        data[0] = new DomainObject();
        data[0].name = "Hans";
        data[1] = new DomainObject();
        data[1].name = "Franz";
    }

    protected void startApp() throws MIDletStateChangeException {
        showOverview();
    }

    /***
     * create an overview, add commands and show it
     */
    private void showOverview() {
        Overview overview = Overview.create(data);
        overview.addCommand(edit);
        overview.addCommand(add);
        overview.addCommand(exit);
        overview.setCommandListener(this);
        Display.getDisplay(this).setCurrent(overview);
    }

    /***
     * create an editor for the given object, add commands and show it
     */
    private void showEditor(DomainObject object, boolean isNew) {
        Editor editor = Editor.create(object, isNew);
        editor.addCommand(ok);
        editor.addCommand(exit);
        editor.setCommandListener(this);
        Display.getDisplay(this).setCurrent(editor);
    }

    public void commandAction(Command c, Displayable d) {
        if(d instanceof Overview) {
            if(c == edit) {
                int i = ((Overview) d).getSelectedIndex();
                showEditor(data[i], false);
            }
            else if(c == add) {
                showEditor(new DomainObject(), true);
            }
            else if(c == exit) {
                this.notifyDestroyed();
            }

        }
        else if(d instanceof Editor) {
            if(c == ok) {
                ((Editor) d).saveValues();
                if(((Editor) d).isNew) {
                    /// search free slot ...
                    int i = 0;
                    for(; i < data.length; i++) {
                        if(data[i] == null) break;
                    }
                    if(i < data.length)  {
                        /// ... and store the new object 
                        data[i] = ((Editor)d).getObject();
                    }
                }
                showOverview();
            }
            else if(c == exit) {
                showOverview();
            }
        }
    }
    protected void destroyApp(boolean unconditional)
            throws MIDletStateChangeException {

    }

    protected void pauseApp() {

    }

}

I hope this helps, don't hesitate to ask ...




回答2:


I'm developing now at work a J2ME app with 10+ of screens adn i use only one MIDlet for my project. I use LWUIT for my UI purposes but you don't have to

every screen extends the Form class, and at the MIDlet i have a screen switching method that looks like this:

public class ExampleMIDlet extends MIDlet {
    private J2meServerGateway gateway;
     .....
    public void changeScreen(Form form) {
        form.show();
    }
}

every form has the MIDlet as parameter and uses the changeScreen method to switch to the next one.

most of the logic is in the forms and i also have an interface that i called J2meServerGateway that separates the view logic (input checks, and handling the result) and the actual calls to the server.

public class BackupForm extends Form implements ActionListener{
  private CloudBackupMIDlet midlet; // as parameter in the constructor
    ......
    public void actionPerformed(ActionEvent ae) {

        if (ae.getSource().equals(signupButton)) {
            doSomething(firstField.getText(), secondField.getText());
        }
    }

    private void doSomething(String st1, String st2) {
      midlet.getGateway().callServer(st1, st2); 
      midlet.changeScreen(new OtherForm(midlet));

    }
}

the J2meServerGatewayImpl is the controller, and uses the model - the objects, the parsers etc...

public class J2meServerGatewayImpl implements J2meServerGateway {
    ......
    public void register(String email, String phone,int password) throws IOException,
        ApiException {
        String params = ...//params
        String resultStr = sendPost(url, params);///actual server call
        //parsing logic etc...
}

hope that it helped



来源:https://stackoverflow.com/questions/24119067/how-do-you-organize-your-code-in-a-j2me-project

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!