`MDIP的生命周期

2008-02-23 09:34:30来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

MDIP的状态有三种:paused,active,destroyed

通常的格式如:
public class MyMIDlet extends MIDlet{
MyMIDlet(){}
protected void startApp() throws MIDletStateChangedException{}
protected void pauseApp(){}
protected void destroyApp(boolean uncoditional) throws MIDletStateChangedException{}
}

各方法的调用情况是:
1.MIDlet被loaded,MIDlet的初始化状态为paused,此时执行初始化,即运行构造方法。如果在初始化MIDlet时出现任何错误的话,MIDlet就直接被置为distroyed状态了。
2.从paused转换为active状态时,设备调用startApp。这个方法名有一定的误导作用,因为此方法是在paused->active时调用的,而非仅仅在app开始的时候调用。
3.从active->paused时,调用pauseApp方法
4.从active->destroyed或paused->destroyed时,调用distroyed方法

与直觉相违背的是:
1.通常情况下,大多数初始化工作是放在startApp中完成的,而非构造函数。这主要是因为移动设备的资源性能都有限,因此此种程序开发的一个宗旨是“在需要用资源的时候申请,用完立刻释放”。另外,根据MDIP的说明,MIDlet只有在调用startApp的时候才能确保拥有对Display的使用权,所以在构造函数中对Display做任何操作有可能出现错误。
2.前面说过,startApp这个函数不是仅仅在MIDlet start的时候才被调用,而是每次从paused状态转换到active状态时都会被调用,因此startApp的格式通常应该是这样
protected void startApp() throws MIDletStateChangedException{
//started is a member of this MIDlet which is boolean with init value false
if(!started){
//initialize
started = true;
}else{
//resume from paused state
}

//the other things
}
3.最重要的在于,MIDlet的状态转换不是由程序自身控制的,而是由host platform控制的:
a.启动时,调用startApp
b.暂停时(比如突然进来一个电话,用户要接),调用pauseApp
c.恢复暂停时,调用startApp
d.程序关闭时,调用destroyApp
当然,在程序中控制状态的转换也是有办法的:
notifyPaused();
notifyDestroyed();
resumeRequest();
这三个函数分别向platform申请active->paused;active/paused->destroyed;paused->active三种状态转换(paused->destroyed的转换是可能的,因为用户在暂停了一个程序后,又想关闭它,总不需要再激活他一下吧)。值得注意的是,在程序中通过这种方式申请状态转换时,platform并不会再去调用pauseApp和destroyApp,因为它认为程序是在准备好了的状况下才会申请状态变迁的。三个转换申请的调用推荐如下格式:
############
pauseApp();
notifyPaused();
############
//destroy后面会具体说明
try{
destroyApp(false);
notifyDestroyed();
}catch(MIDletStateChangedException msce){
//MIDlet don't want to be destroyed
}
############
//resumeRequest的意思是platform在不久后调用startApp,因此不用先做状态转换的准备
resumeRequest();
############
还有一点值得注意的是,由于destroyApp可能在active时被调用,也可能是paused时被调用,有时候有必要检查一下MIDlet当时的状态。destroyApp的作用是释放MIDlet占有的所有资源,而paused却要释放暂时不需要的资源并保存需要的状态变量,所以在destroy函数中针对不同状态做不同的资源释放有时是很有必要的。

!!关于MIDletStateChangedException
startApp和destroyApp都会抛出这个异常,一一说明如下:
*startApp:
1.当出现了transient failuer时,即遇到暂时的问题导致startApp运行不下去,它会抛出一个MIDletStateChangedException,然后回到paused状态,以便下次再startApp;
2.当出现non-transient failuer时,notifyDestroyed就应该被调用了(后面说明);
3.当出现了RuntimeException时,MIDlet就立刻被destroyed了——当然destroyApp会被先调用。

*destroyApp:
destroyApp的作用是释放所有的资源(包括各个线程)。其参数为true表示无条件释放(正如其名称unconditional)。
1.当platform进行状态转换时,unconditional是true;
2.当MIDlet自身要求进行destroy时——比如响应用户按下EXIT按钮事件,建议使用前述的方式:
try{
destroyApp(false);
notifyDestroyed();
}catch(MIDletStateChangedException msce){
//MIDlet don't want to be destroyed
}
false表示,当释放资源时遇到了某些不能释放的东西——比如需要保存的文件——就抛出一个MIDletStateChangedException,以便做相应的处理。显然,这种方式更加friendly。
另外,对于MIDlet来说,notifyDestroyed()是唯一可以强行退出程序的方法。调用Syste.exit或Runtime.exit都会抛出SecurityException。

最后需要注意一个细节是:startApp会运行到结束,然后却不会自动转入destroyed 或 paused状态,而是停留在active的状态——MIDlet程序通常都是事件驱动的,谁也不希望程序在用户没有发出退出命令时就自己退了出去。

上一篇: 较为复杂的 Hibernate 数据映射
下一篇: 一年以来对Java的一些感想!!

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:java编写TCP方式的通信程序

下一篇:较为复杂的 Hibernate 数据映射