选择显示字体大小

入门-j2me学习日记之-利用定时器类模拟midlet外部事件

入门-j2me学习日记之-利用定时器类模拟midlet外部事件

作者:snail


版权申明:可以转载,请保留作者信息和来源地址:
作者:snail
地址:http://www.matrix.org.cn/resource/article/43/43851_j2me.html


前面提到midlet程序本身可以通过调用notifypaused()请求自己从活动状态进入暂停状态;调用notifydestroyed()请求进入销毁状态;调用resumerequest()请求恢复到活动状态。但是具体应该怎么使用呢?怎样通过程序本身模拟状态之间的转换呢?

这些都可以通过java.util包中的timer 和timertask 类来实现。听说nokia的模拟器最接近真机,所以这次程序选择nokia s40 开发环境(唯一的不足就是不支持中文)。具体看如下演示程序:

import javax.microedition.midlet.midlet;
import java.util.*;
/*
* 创建日期 2005-10-8
*
* todo 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - java - 代码样式 - 代码模板
*/

/**
* @author snail
*
* todo 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - java - 代码样式 - 代码模板
*/
public class mytimertask extends timertask {

private midlet midlet;

/**
  *
  */
public mytimertask(midlet midlet) {
  // todo 自动生成构造函数存根
  system.out.println("mytimertask contructor");
  this.midlet = midlet;
}
public void run(){
  system.out.println("run() called");
  midlet.resumerequest();
}


}




import javax.microedition.midlet.midlet;
import javax.microedition.lcdui.*;
import java.util.*;
import javax.microedition.midlet.midletstatechangeexception;
/*
* 创建日期 2005-10-8
*
* todo 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - java - 代码样式 - 代码模板
*/

/**
* @author snail
*
* todo 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - java - 代码样式 - 代码模板
*/
public class midlettest extends midlet implements commandlistener{

private timer timer;
private mytimertask mtk;
private command exit;
/**
  *
  */
public midlettest() {
  system.out.println("midlettest constructor");
  //初始化timer对象
   timer = new timer();
}

/* (非 javadoc)
  * @see javax.microedition.midlet.midlet#startapp()
  */
protected void startapp() throws midletstatechangeexception {
  // todo 自动生成方法存根
  system.out.println("startapp called");
  exit = new command("exit", command.exit, 1);
  form f = new form("midlettest");
  string s = new string("i'll come back soon!");
  f.append(s);
  f.addcommand(exit);
  f.setcommandlistener(this);
  display.getdisplay(this).setcurrent(f);
  try{
   //画面停留4秒 即活动状态 时间为4秒
   thread.sleep(4000);
  }catch(exception e){}
  
  system.out.println("ready to paused");
  try{
   mtk = null;
      //获得当前midlet基类的引用(向上转型)
      mtk = new mytimertask(this);
      //执行该任务等待 2秒
      timer.schedule(mtk, 2000);
      //请求进入暂停状态
      pauseapp();
      notifypaused();
  }catch(exception e){}
  
}

/* (非 javadoc)
  * @see javax.microedition.midlet.midlet#pauseapp()
  */
protected void pauseapp() {
  // todo 自动生成方法存根
  system.out.println("pauseapp called");

}

/* (非 javadoc)
  * @see javax.microedition.midlet.midlet#destroyapp(boolean)
  */
protected void destroyapp(boolean arg0)throws midletstatechangeexception {
  // todo 自动生成方法存根
  system.out.println("destroyapp called:" + arg0);
  //停止timer ,和timertask合同期满,脱离关系
  timer.cancel();

}
public void commandaction(command c, displayable d){
  if(c == exit){
   try{
   destroyapp(false);
   notifydestroyed();
   }catch(midletstatechangeexception e){}
  }
}

}



    通过上面程序可以看到, timer必须配合timertask才能实现定时器功能。timertask是一个抽象类 ,必须有子类继承它并重载其run()方法。timer实例一个对象timer,该对象通过调用schedule方法调度timertask子类对象执行其run()方法,从而达到使midlet 周期性的在暂停状态和活动状态之间不停的切换。

    mytimertask类其实很简单,该类内部定义了一个私有数据 midlet 对象,通过它可以调用resumerequest()方法使midlet 程序请求从暂停恢复到活动状态。

    midlettest 类中实现了commandlistener接口,所以必须要重载其对应的commandaction(command c, displayable d)方法。使程序能够对用户的操作做出响应。类似的在awt中我们见多了。我们可以执行"exit",使程序主动进入销毁状态。具体可以观察控制台信息:

midlettest constructor
startapp called
ready to paused
mytimertask contructor
pauseapp called
run() called
startapp called
destroyapp called:false
ready to paused
mytimertask contructor



便于理解,可以假设有如下场景:

      上班时间,老板不在,用手机玩会游戏先!游戏ing…… 有电话!接个电话先,over! 继续游戏! 不好 b老板来了,"exit" 退出游戏!!    

      可以看到程序不停的在活动和暂停状态之间切换。当我们"exit"程序时 ,看到控制台打印信息 , 传入destroyapp 的是false,即非强制性销毁。前面已经了解,midlet主动请求状态转换需要调用的方法,并且一般都要先调用相应的pauseapp() destroyapp()方法。这里不在多说。现在关心的是:具体怎么通过timer 和timertask 实现的呢?仔细观察程序,有这两句:

mtk = new mytimertask(this);
timer.schedule(mtk, 2000);


      首先实例mytimertask对象,并将this作为参数传递给构造方法。this指向的是当前midlet。观察其构造方法,参数类型是midlet ,而midlettest 只是其导出类。这里隐藏了向上转型。(具体可以参考j2se中继承与多态部分。)获得了midlet的引用 ,就象手里拿着遥控器一样 ,timer就可以控制midlet了。timer通过schedule方法设置周期,执行该任务 等待两秒。接下来的两句 ,就是程序主动请求进入暂停。另外,还注意到 timer 在构造方法中,所以只被调用一次,而mtk却每次调用startapp时都会被重新new一次。这是因为只有调用cancel() timer和timertask脱离关系时 ,timertask才能被安排其他任务。

    如果把thread.sleep(4000); 这个try{}catch(){}块注释掉,我们发现 midlet从暂停进入活动状态后 屏幕只是很快的一闪 就又进入暂停状态了。所以这段代码 就是让活动状态多停留一会 让他sleep 4秒。

    再看看这段代码:

try{
   mtk = null;
      //获得当前midlet基类的引用(向上转型)
      mtk = new mytimertask(this);
      //执行该任务等待 2秒
      timer.schedule(mtk, 2000);
      //请求进入暂停状态
      pauseapp();
      notifypaused();
  }catch(exception e){}  



现在把其中的try 和catch 注释掉 其他的保留。当再次运行程序,"exit",看看控制台打印的信息:

midlettest constructor
startapp called
destroyapp called:false
ready to paused
mytimertask contructor
startapp threw an exception
java.lang.illegalstateexception: timer already cancelled.


    在startapp()中有异常被抛出。分析控制台信息,应该是发生在destroyapp已经被调用但notifydestroyed()方法还没执行时。此时cancel()方法已经执行完毕,timer和timertask 的合作关系也被迫解除。startapp()继续执行,当程序执行到

timer.schedule(mtk, 2000);

这句时 ,因为关系已经解除,startapp()无法继续, 所以抛出了上面的异常。

       timer类还有其他的方法,具体可以参考api中java.util包。

       到此,就暂告一段落!旅行还将继续……


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons