MIDlet工作原理-阿里云开发者社区

开发者社区> code_xzh> 正文

MIDlet工作原理

简介: 题记 :  现在的J2ME用户已经是日益减少 , 开发也在转型! 无奈之下也不得不写下这系列文章来别了j2me ,也是对过去的一些总结吧!         ①: 所有Kjava必须会继承自javax.microedition.midlet.MIDlet类的。其中定义了三个抽象方法(abstract),因此我们撰写的MIDlet必须实现它们。这三个抽象方法是:        
+关注继续查看

题记 :  现在的J2ME用户已经是日益减少 , 开发也在转型! 无奈之下也不得不写下这系列文章来别了j2me ,也是对过去的一些总结吧!

        ①: 所有Kjava必须会继承自javax.microedition.midlet.MIDlet类的。其中定义了三个抽象方法(abstract),因此我们撰写的MIDlet必须实现它们。这三个抽象方法是:

          1.     startApp()   转到运作状态

          2.     pauseApp()   转到停止状态

          3.     destroyApp() 转到消灭状态

         应用程序管理器通过这三个抽象方法来控制MIDlet的生命周期。因此,所有的MIDlet都必须实现这三个方法 !

        ②:两种控制应用程序的生命周期的方式

   1.  由应用程序管理器来控制(硬控制)

               

                                                                                 生命周期

        

    如上图可知midlet在进入某个状态之前都会调用相应的函数然后进入该状态。 这都是应用程序管理器调用的,但是设计者考虑到了如果程序员自己调用了这里面的情况。

     讨论一: 如果程序员自己调用了这里面的情况的话应用程序管理器会做如何的改变呢?

       官方文档如此回答:  通常不会发生错误,但是也不会造成状态的转换,只是当成一个单纯的函数调用而已

       在此做了一个小的案例来说明一下 :

        情况一 :

[java] view plain copy
 print?
  1. public class MidTest extends MIDlet {  
  2.     public  MidTest() {  
  3.           System.out.println("MidTest()");  
  4.     }  
  5.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException {  
  6.         System.out.println("destroyApp()");  
  7.     }  
  8.   
  9.     protected void pauseApp() {  
  10.         System.out.println("pauseApp()");  
  11.     }  
  12.     protected void startApp() throws MIDletStateChangeException {  
  13.         System.out.println("startApp()");  
  14.         destroyApp(true);  
  15.     }  
  16.   
  17. }  

当我们程序员自己在startApp() 里面调用destroyApp(true);(这个函数的参数后面会讲到) 时,它的结果如下:

    MidTest()
    startApp()
    destroyApp()

但是程序并没有退出! 说明了一个情况就是 : 自己调用的时候是不会进行状态的切换的

 情况二:当我们关闭程序的时候得到的结果是: destroyApp() 说明了当关闭程序的时候应用程序管理器会调用此方法的!

 

讨论二 :如何合理利用startApp()?pauseApp()  ? destroyApp(boolean arg0) ?

 从上图的生命周期可以看到startApp()这个函数是不止一次被调用的(第一次new) 当恢复了pause后也会进入这种状态。所以做为开发人员的我们那些没有必要重新初始化的操作(特别是加载一些资源的时候)不要放到这里面,以免浪费时间! 最好的做法就是:放在构造函数做初始化动作

 应用程序管理器会因为某些状况,必须让MIDlet停止运作。例如手机来电,或者闹铃响了,或者用户强行切换到其他程序执行。在这些情况吓,为了避免MIDlet占用太多系统资源,应用程序管理器会调用该MIDlet的pauseApp(),这时应该在pauseApp()之中适时的释放一些非必需的资源,等到返回到运作状态时,应用程序管理器会重新调用startApp(),这时再将这些被释放的资源重新加载

 当MIDlet进入停止状态时,不应该使用任何资源。如果应用程序管理器调用pauseApp()时产生异常,MIDlet就应该立刻进入消灭状态。同样的情况也发生在destroyApp(),通常调用此方法时,表示MIDlet要被关闭了。所以,应该在这里释放MIDlet所分配的资源。只要MIDlet进入消灭状态,就无法再回头。如果时系统自己调用destroyApp(),那么在其执行时万一发生异常,这些异常将被忽略,MIDlet一样会被关闭。             

          2. 由程序员来控制(软控制) :由程序员来决定是否退出程序

   

当MIDlet主动要将MIDlet的状态由运作状态变成停止状态,那么我们直接调用pauseApp()函数,只会执行pauseApp()之中的程序代码,无法改变MIDlet的状态,MIDlet必须调用notifyPaused()来通知应用程序管理器,应用程序管理器收到通知后,才会判断是否要让MIDlet进入停止状态。

    由MIDlet调用notifyPaused()与应用程序管理器主动要求停止,两者是有所差别的。主要在于应用程序管理器主动要求停止时,pauseApp()会被调用;由MIDlet调用notifyPaused()时,pauseApp()不会被调用。但两者都会让MIDlet进入停止状态,所以在MIDlet自己调用notifyPaused()之前,最好自己也先调用pauseApp()比较合适。

 实例如下: 

[java] view plain copy
 print?
  1. public class MidTest extends MIDlet {  
  2.     public  MidTest() {  
  3.           System.out.println("MidTest()");  
  4.     }  
  5.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException {  
  6.         System.out.println("destroyApp()");  
  7.     }  
  8.   
  9.     protected void pauseApp() {  
  10.         System.out.println("pauseApp()");  
  11.     }  
  12.     protected void startApp() throws MIDletStateChangeException {  
  13.         System.out.println("startApp()");  
  14.         notifyPaused() ;  
  15.     }  

结果是 :

   

  MidTest()
  startApp()
  表明了程序员自己调用了notifyPaused() 其实并没有调用pauseApp()  所以这里最好的写法是在notifyPaused() 之前调用pauseApp()  ;

    同样的情况也发生在notifyDestroyed()与destroyApp()。除非时系统强制关闭MIDlet,否则最好MIDlet先调用destroyApp(),然后再调用notifyDestroyed(),请应用程序管理器帮我们将MIDlet转换到消灭状态,最后结束MIDlet的运作。destoryApp()有个布尔值作为参数,根据MIDP规范,如果传入true,那么MIDlet不管如何应该强制无条件释放所有资源,然后让应用程序管理器结束MIDlet的运作,这属于系统或硬件强制关闭MIDlet的情形。如果用户调用notifyDestoryed()来结束MIDlet,那么在调用destroyApp()时,最好传入false,代表这并非系统或硬件强制关闭,这时如果MIDlet不希望结束执行,可以通过抛出MIDletStateChangeException异常告知调用者:我还不想被消灭,稍后再试。

 ③:总结: 

从上面我们也可以看出startApp()、pauseApp()以及destroyApp()并非控制MIDlet生命周期的函数,它们只是一个提供我们初始化资源、释放资源的地方而已。真正的地方还是软控制里面的那些函数! 

 明天继续这个系列的系统原理,谢谢大家! 

补充: 今天看到论坛上有朋友提出了这样一个问题 : 两个midlet的切换!

              我们知道应用程序初始化后就会在建立一个对应的虚拟机,并创建一个对应的虚拟机实例! 如果向如下来创建的话:

           

[java] view plain copy
 print?
  1. public class Test extends MIDlet {  
  2.        static Display display ;  
  3.         public Test()  
  4.         {  
  5.     display = Display.getDisplay(this) ;  
  6.         System.out.println("Test()");  
  7.          }  
  8.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException {  
  9.        System.out.println("destroyApp ");  
  10.     }  
  11.     protected void pauseApp() {  
  12.     }  
  13.     protected void startApp() throws MIDletStateChangeException {  
  14.            System.out.println("startApp ");  
  15.            new Test2() ;  
  16.     }  
  17. }  

那么在new Test2() 这一步的时候其实原来的虚拟机实例是没有消失的。这时就是试图在一个虚拟机里创建两个实例那是不允许的! 系统就会抛出:

  java.lang.SecurityException: Application not authorized to access the restricted API(访问受限的API)

 那么另一个问题来了。你可能会说那么我们先将Test 使用notifyDestroyed() ;进行销毁。然后再次创建就是一个实例了

其实不然,正如我上面讲解软控制的时候提到的。notifyDestroyed()  这个东西只是提醒应用程序管理器,我要死了。把资源都释放了吧。但是应用程序管理器会去检测一下还有没有存活的东西,然后才回去摧毁。如果你这样来调用的话!

[java] view plain copy
 print?
  1. protected void startApp() throws MIDletStateChangeException {  
  2.     System.out.println("startApp ");  
  3.     notifyDestroyed() ;  
  4.     new Test2() ;  
  5.    }  

那么当Test()的应用程序管理器检查到了notifyDestroyed() 正准备释放资源了。才发现new Test2() 这个东西并不是我的,但是却要我去摧毁,那么肯定也会抛出上面的异常了!

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6782 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
2714 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4345 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
7718 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
5359 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
9394 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
2109 0
+关注
code_xzh
对前端移动客户端技术比较擅长。著有《React Native移动开发实战》和《Kotlin入门与实战》和《Weex跨平台实战》,《React Native移动开发进阶》即将出版,正在努力完成《Flutter跨平台开发实战》
717
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载