Basic query about what's going on with the stack in a Java ME app
我以 Java SE 背景(基本上没有 GUI/ActionListener 经验)来到 Java ME,但由于缺少 main() 方法,我仍然有点迷失方向。也许我应该说我正确地学习了 Java SE,但我试图通过谷歌搜索大量"Java ME for dummies"页面来自学 Java ME,这并不理想。我曾以为我会侥幸逃脱,但现在不太确定了。
为了让 Java ME 脚本启动并运行,我为基类编写代码,但没有静态 main() 方法。相反,我让类扩展 MIDlet,然后编写方法 startApp()、pauseApp() 和 destroyApp()。不过,这些方法似乎不是静态的(从某种意义上说,我在这里查看的"hello World"应用程序并未将它们创建为静态方法)。
那么第一个问题:当我开始在手机上运行我的 MIDlet 时,是否真的在堆栈上创建了一个基类的实例?
在那之后,我更加困惑了。大概我的第一个问题的答案是肯定的,我可以将实例称为"this"。现在在 StartApp() 中,我将创建一个表单并显示它。所以我的部分代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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. } |
当 MIDlet 启动时,我怀疑在堆栈上创建了一个 TestMidlet 实例。然后运行 ??startApp() 方法,该方法创建一个表单并将其显示在屏幕上。现在在我天真的眼里,接下来发生的是 startApp() 现在用完了要执行的命令,然后结束。
第二个问题:我是否正确假设 (a) startApp() 确实完成但 (b) TestMidlet 的实例由于某种原因不能用于垃圾收集,因为表单通过 commandListener 以某种方式使其保持活动状态?在这一点上,我真的不清楚是否有当前正在运行的堆栈。据推测,关键是未命名的 TestMidlet 本身就是一个 CommandListener,因此仍然很忙,因此尽管我看不到任何引用它的东西,但不想用于垃圾收集。
最后,当用户在表单中做出选择时,这个未命名的 TestMidlet 实例会在其 commandAction() 方法开始运行的意义上弹回行动?特别是我仍然可以在它的 commandAction 方法中访问这个神秘的未命名的 TestMidlet 实例,使用"this"?
这一切我都说清楚了吗?
当您开始在手机上运行 MIDlet 时,会以与
您可以将上述实例称为
鉴于您的 Java SE 背景,我希望这听起来很熟悉。这里真的没有魔法 - 将其视为在运行生命周期序列的过程中调用
在
的实例上调用 notifyDestroyed()
关于垃圾回收,你可以安全地应用从 Java SE 获得的一般理解,保存缺少的方法
这个未命名的 TestMidlet 实例在它的 commandAction() 方法开始运行的意义上弹回动作 - 如果您正确设置命令侦听器并添加命令。特别是您仍然可以在其 commandAction 方法中访问这个神秘的未命名的 TestMidlet 实例,使用 "qualified this" JLS 15.8.4 Qualified this like
鉴于您对所有这些命令和侦听器感到困惑,我建议您在实验代码中去掉实现 CommandListener,大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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?
不完全是。鉴于您的问题,您的"Java ME for dummies"页面的级别似乎已经过大,因此是时候切换到更严肃的资源了。
值得检查的是:
- 学习路径:MIDlet 生命周期 - SDN 教程
- MIDP 2 (JSR 118) 规范。获取 PDF 版本,跳过方法和类的详细信息以进行介绍性阅读。
- 维基百科上的 Java ME 文章,让您知道除了 MIDP 之外还有什么
请记住,有一个更新版本的 MIDP 规范 - JSR 271,尽管我不建议您深入研究它,除非您明确知道您的目标是这个版本。
您遇到的一些困难来自于您的背景基本上没有 GUI/ActionListener 经验。准备好适应"UI 风格思维"需要一些时间。如果您还没有阅读它,请查看 java.net
上的 J2ME 教程,第 2 部分:使用 MIDP 2.0 的用户界面