Базовый запрос о том, что происходит со стеком в приложении Java ME

Я перехожу к Java ME с опытом работы с Java SE (который практически не предполагает использования GUI / ActionListener) и все еще немного дезориентирован из-за отсутствия метода main (). Возможно, мне следует сказать, что я изучил Java SE должным образом, но пытаюсь научить себя Java ME, ища в Google множество страниц «Java ME для чайников», что не идеально. Я предполагал, что мне это сойдет с рук, но сейчас я гораздо менее уверен.

Чтобы запустить и запустить сценарий Java ME, я пишу код для базового класса, но не имею статического метода main (). Вместо этого я расширяю класс MIDlet, а затем пишу методы startApp (), pauseApp () и destroyApp (). Однако эти методы не кажутся статическими (в том смысле, что приложение "hello World", которое я здесь рассматриваю, не создает их как статические методы).

Тогда первый вопрос: когда я запускаю свой мидлет, скажем, на моем телефоне, действительно ли создается экземпляр базового класса в стеке?

После этого я еще больше запутался. По-видимому, ответ на мой первый вопрос - да, и я могу назвать этот экземпляр «этим». Теперь в StartApp () я собираюсь создать форму и отобразить ее. Итак, часть моего кода выглядит так:

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.
    }

Я подозреваю, что при запуске мидлета в стеке создается экземпляр TestMidlet. Затем запускается метод startApp (), который создает форму и отображает ее на экране. На мой наивный взгляд, дальше происходит то, что у startApp () заканчиваются команды для выполнения, а затем он завершается.

Второй вопрос: правильно ли я предполагаю, что (а) startApp () действительно завершается, но (б) экземпляр TestMidlet по какой-то причине не становится доступным для сборки мусора, потому что каким-то образом форма поддерживает его через commandListener? На данный момент мне действительно неясно, существует ли текущий стек. По-видимому, дело в том, что безымянный TestMidlet сам является CommandListener и, следовательно, все еще занят, поэтому не хочет становиться доступным для сборки мусора, несмотря на то, что я не вижу ничего, относящегося к нему.

Наконец, когда пользователь делает выбор в форме, этот безымянный экземпляр TestMidlet возвращается в действие в том смысле, что его метод commandAction () начинает выполняться? И, в частности, я все еще могу получить доступ к этому таинственному безымянному экземпляру TestMidlet в его методе commandAction, используя "this"?

У меня все прямо?


person Kevin Buzzard    schedule 30.01.2012    source источник
comment
mainForm.setSelectCommand не будет компилироваться, пока вы определяете mainform как lcdui.Form - вы имели в виду mainForm.addCommand в этом примере кода?   -  person gnat    schedule 31.01.2012
comment
Как видите, я все еще новичок в этой игре для ME. Я хотел сделать mainForm списком. Я редактировал.   -  person Kevin Buzzard    schedule 31.01.2012
comment
Понимаю - теперь это имеет смысл. Кстати, я обновил фрагмент кода в моем ответе, чтобы использовать список вместо формы   -  person gnat    schedule 31.01.2012


Ответы (1)


  1. когда вы запускаете свой мидлет на своем телефоне, экземпляр TestMidlet создается так же, как это происходит для new Object()
    вы можете ссылаться на приведенный выше экземпляр как this

  2. startApp() - типичный "пошаговый метод" согласно шаблону метода шаблона
    с учетом вашего опыта работы с Java SE. Думаю, это звучит знакомо. На самом деле никакой магии здесь нет - думайте об этом как о некоторой структуре, вызывающей startApp() в ходе выполнения последовательности жизненного цикла, которая для вас невидима. Поищите в Интернете что-нибудь вроде жизненного цикла мидлета, если вас интересуют более подробные сведения.

  3. в последней инструкции в startApp этот метод действительно завершается - вы здесь. Но, кроме того, на самом деле ничего волшебного не происходит - экземпляр TestMidlet жив и здоров, работает под «средой MIDP», пока либо пользователь не остановит ваше приложение, либо ваш код не вызовет notifyDestroyed () на экземпляре TestMidlet

  4. Что касается сборки мусора, вы можете смело применять здесь общие сведения, взятые из Java SE, сохраните отсутствующий метод Object.finalize() (обычно будьте готовы к тому, что в MIDP отсутствуют некоторые другие методы и классы, к которым вы привыкли в Java SE)

  5. этот безымянный экземпляр TestMidlet возвращается в действие в том смысле, что его метод commandAction () начинает выполняться - если вы правильно настроили прослушиватель команд и добавили команду. И, в частности, вы все еще можете получить доступ к этому таинственному безымянному экземпляру TestMidlet в его методе commandAction, используя "квалифицированный this" JLS 15.8.4 квалифицировано как TestMidlet.this

Учитывая, насколько сложно вы относитесь ко всем этим командам и слушателям, я бы порекомендовал избавиться от реализует CommandListener в вашем экспериментальном коде примерно следующим образом:

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
    }
}

У меня все прямо?

Не совсем. Учитывая ваши вопросы, похоже, что вы переросли уровень страниц "Java ME для чайников", так что пора переключиться на более серьезные ресурсы.

Стоит проверить:

Имейте в виду, что существует более новая версия спецификации MIDP - JSR 271. , хотя я бы не рекомендовал углубляться в это, если вы определенно не знаете, что ориентируетесь на эту версию.

Некоторые из трудностей, с которыми вы сталкиваетесь, связаны с тем, что ваш опыт по существу не предполагает взаимодействия с графическим интерфейсом пользователя / ActionListener. Будьте готовы к тому, что потребуется некоторое время, чтобы приспособиться к «мышлению в стиле пользовательского интерфейса». Если вы еще не читали его, ознакомьтесь с J2ME Tutorial, Часть 2: Пользовательские интерфейсы с MIDP 2.0 на java.net

person gnat    schedule 31.01.2012