Search code examples
java-memidplcdui

Basic query about what's going on with the stack in a Java ME app


I am coming to Java ME with a Java SE background (which involves essentially no GUI/ActionListener experience) and am still a little disorientated by the lack of a main() method. Perhaps I should say that I learnt Java SE properly but am attempting to teach myself Java ME by googling for lots of "Java ME for dummies" pages, which is not ideal. I had assumed that I'd get away with it, but am much less sure now.

To get a Java ME script up and running, I write code for a base class, but have no static main() method. Instead I make the class extend MIDlet and then write methods startApp(), pauseApp() and destroyApp() . These methods do not appear to be static though (in the sense that the "hello World" app I'm looking at here doesn't create them as static methods).

First question then: when I start running my MIDlet on, say, my phone, is an instance of the base class actually created on the stack?

After that, I'm even more confused. Presumably the answer to my first question is yes, and I can refer to the instance as "this". Now in StartApp() I'm going to create a Form and display it. So part of my code looks like this:

public class TestMidlet extends MIDlet implements CommandListener {

    List mainForm;
    Command comSelect;

    protected void startApp() throws MIDletStateChangeException {

        mainForm = new List("Menu",List.IMPLICIT);

        mainForm.append("this one?",null);
        mainForm.append("or this one?",null);

        comSelect=new Command("Select",Command.ITEM,1);
        mainForm.setSelectCommand(comSelect);
        mainForm.setCommandListener(this);

        Display.getDisplay(this).setCurrent(mainForm);
    }

    public void commandAction(Command c,Displayable d) {
        // we will end up here when the user makes a selection in mainForm.
    }

When the MIDlet is launched, I suspect an instance of TestMidlet is created on the stack. The method startApp() is then run, which creates a form and displays it on the screen. Now to my naive eyes, what happens next is that startApp() now runs out of commands to execute, and then finishes.

Second question: am I right in assuming that (a) startApp() does actually finish but (b) the instance of TestMidlet for some reason does not become available for garbage collection, because somehow the form is keeping it alive via commandListener? I am really unclear, at this point, about whether there is a currently-running stack. Presumably the point is that the unnamed TestMidlet is itself a CommandListener and is hence still busy, so doesn't want to become available for garbage collection despite the fact that I can't see anything referring to it.

Finally, when the user makes a choice in the form, this unnamed instance of TestMidlet springs back into action in the sense that its commandAction() method starts running? And in particular I can still access this mysterious unnamed instance of TestMidlet in its commandAction method, using "this"?

Do I have all this straight?


Solution

    1. when you start running your MIDlet on your phone an instance of the TestMidlet is created in the same way as it happens for new Object()
      you can refer to above instance as this

    2. startApp() is a typical "step method" as per Template method pattern
      given your Java SE background I expect it sounds familiar. No magic here really - think of it as some framework invoking startApp() in the course of running life cycle sequence which is invisible to you. Search web for something like MIDlet life cycle if you're interested in more details.

    3. at the last statement in startApp this method finishes indeed - you are right here. But further, nothing magical happens really - TestMidlet instance is alive and well, running under "MIDP framework" until either user stops your application or your code invokes notifyDestroyed() on the instance of TestMidlet

    4. regarding garbage collection, you can safely apply general understanding taked from Java SE here, save the missing method Object.finalize() (be generally prepared that MIDP lacks some other methods and classes you get used to in Java SE)

    5. this unnamed instance of TestMidlet springs back into action in the sense that its commandAction() method starts running - if you properly set command listener and added a command. And in particular you can still access this mysterious unnamed instance of TestMidlet in its commandAction method, using "qualified this" JLS 15.8.4 Qualified this like TestMidlet.this

    Given how much confusion you feel related to all these commands and listeners, I would recommend to get rid of implements CommandListener in your experimental code, about as follows:

    public class TestMidlet extends MIDlet {
    
        List mainForm;
        Command comSelect;
    
        protected void startApp() throws MIDletStateChangeException {
    
            mainForm = new List("Menu",List.IMPLICIT);
    
            mainForm.append("this one?",null);
            mainForm.append("or this one?",null);
            mainForm.append("Exit",null);
    
            comSelect=new Command("Select",Command.ITEM,1);
            mainForm.addCommand(comSelect); // note addCommand here
            mainForm.setSelectCommand(comSelect); // convenient thing BTW
    
            mainForm.setCommandListener(new CommandListener() {
                public void commandAction(Command c,Displayable d) {
                    // we'll end up here when the user makes a selection in mainForm.                   
                    List list = (List)d;
                    // note d refers to mainForm here, that's why it's OK to cast above
                    if (list.getString(list.getSelectedIndex()).equals("Exit")) {
                        // if user selected exit
                        TestMidlet.this.notifyDestroyed(); // exit the midlet
                    }
                }
            });
            // display the form
            Display.getDisplay(this).setCurrent(mainForm);
            // startApp finishes here
        }
    }
    

    Do I have all this straight?

    Not quite. Given your questions it looks like you overgrown level of "Java ME for dummies" pages so that it's about time to switch to more serious resources.

    Things worth checking are:

    Keep in mind that there is a newer version of MIDP specification - JSR 271, although I would not recommend diving into it unless you definitely know that you are targeting this version.

    Some of the difficulties you experience come from the fact that your background involves essentially no GUI/ActionListener experience. Be prepared that it will take some time to adjust to "UI style thinking". If you didn't read it yet, check J2ME Tutorial, Part 2: User Interfaces with MIDP 2.0 at java.net