`MDIP的生命周期

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程序通常都是事件驱动的,谁也不希望程序在用户没有发出退出命令时就自己退了出去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值