动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
   程序开发 → 阅读文章

 MIDlet中实现程序管理器和多语言程序

作者来源: 
阅读 数 124 人次 , 2006-4-25 9:10:00 


  在MIDlet编程中,很多系统的属性要通过一个MIDlet实例来访问,比如Display.getDisplay,那么在需要切换界面的类里面你必须把MIDlet实例或者Display实例传送给他,尤其在设计弹出和可以返回的界面时。没有更好的办法吗?又比如程序的暂停功能,有没有根方便的方法把他们集成起来?还有错误处理,程序退出等等,利用以往的方法是不是很不爽?

  嗯,真是不爽,于是我写了这个程序管理器:App。首先看他的组织方式:

static App instance;
Display disp_;
MIDlet app_;
public static void createInstance(MIDlet app)
{
 if(instance==null)
  instance=new App();
  instance.app_=app;
  instance.disp_=Display.getDisplay(app);
}
private App()
{}

  每个MIDlet只需要一个管理器,所以只允许一个实例。这样,我们就可以通过静态方法提供一些系统参数的访问方法:

public static String getProperty(String name)
{
 return instance.app_.getAppProperty(name);
}
public static Display getDisplay()
{
 return instance.disp_;
}

  他还应该提供返回前一屏的功能,如何实现呢?既然有了display,难道每次还是要App.getDisplay().setCurrent(xxx)?索性提供一个App.setCurrent():

public static void setCurrent(Displayable d)
{
 if(d!=instance.old_)
 {
  instance.old_=instance.disp_.getCurrent();
  instance.disp_.setCurrent(d);
 }
}

  对了,我们就利用这个来实现切换到前一屏的功能:

public static void restore()
{
 if(instance.old_!=null)
 {
  instance.disp_.setCurrent(instance.old_);
  instance.old_=null;
 }
}

  接下去该轮到程序暂停和恢复的处理以及一些常用命令

public static boolean restart()
{
 if(instance.paused_)
 {
  instance.disp_.setCurrent(instance.bef_);
  instance.paused_=false;
  return true;
 }
 else
  return false;
}
public static void pause()
{
 instance.bef_=instance.disp_.getCurrent();
 instance.paused_=true;
}
public static void exit()
{
 instance.app_.notifyDestroyed();
}
public static void handleError(String msg, Exception ex)
{
 System.out.println(msg+"::"+ex);
}

  下面讲述多语言支持的集成。语言选择当然需要一个界面,就是这个:

class LanguageMenu extends List implements CommandListener
{
 Command cmdOK_;
 Object[] langlist_=new Object[]{ "Chinese","zh_cn",null, "USA","en_us",null};

 public LanguageMenu()
 {
  super("Select Language",List.IMPLICIT);
  for(int i=0;i {
   this.append((String)langlist_[i],(Image)langlist_[i+2]);
  }
  cmdOK_=new Command("OK",Command.SCREEN,2);
  this.addCommand(cmdOK_);
  this.setSelectCommand(cmdOK_);
  this.setCommandListener(this);
 }

 public void commandAction(Command c, Displayable d) {
  if(c==cmdOK_)
  {
   ......
  }
 }
}

  这个时候又碰到了一个在实现SNProtector的时候碰到的问题,如何中断程序然后在用户确认后继续执行?在制作SNProtector的时候采用了Pause-Resume的方法实现了功能,但是效果不太理想。那只好自己多写些代码避免用户的麻烦。

  这个方法通过引入一个IApp的接口,MIDlet类要实现这个接口:

public interface IApp
{
 public void start();
}

  然后把原来在startApp的内容放入start之中。在App中增加一个方法:

static void continueRun()
{
 if(instance.app_ instanceof IApp)
 {
  ((IApp)instance.app_).start();
 }
}

  好了,然后该具体实现一下语言选择菜单了:

class LanguageMenu extends List implements CommandListener
{
 Command cmdOK_;
 Object[] langlist_=new Object[]{
  "Chinese","zh_cn",null, "USA","en_us",null
 };

 public LanguageMenu()
 {
  super("Select Language",List.IMPLICIT);
  for(int i=0;i {
   this.append((String)langlist_[i],(Image)langlist_[i+2]);
  }
  cmdOK_=new Command("OK",Command.SCREEN,2);
  this.addCommand(cmdOK_);
  this.setSelectCommand(cmdOK_);
  this.setCommandListener(this);
 }

 public void commandAction(Command c, Displayable d) {
  if(c==cmdOK_)
  {
   int cmd=this.getSelectedIndex();
   instance.lang_=(String)langlist_[cmd*3+1];
   try
   {
    RecordStore.deleteRecordStore(LanguageRMS);
   }
   catch(Exception ex)
   {}
   try
   {
    RecordStore rs=RecordStore.openRecordStore(LanguageRMS,true);
    byte[] buf=instance.lang_.getBytes();
    rs.addRecord(buf,0,buf.length);
    rs.closeRecordStore();
   }
   catch(Exception ex)
   {}
   continueRun();
  }
 }
}

  同样通过RMS保存了用户的选项,不用每次都选择,最后当然需要有个函数对这些工作进行调度:

public static boolean selectLanguage()
{
 boolean r=(instance.lang_!=null);
 if(!r)
 {
  try
  {
   RecordStore rs=RecordStore.openRecordStore(LanguageRMS,true);
   RecordEnumeration e=rs.enumerateRecords(null,null,false);
   if(e.hasNextElement())
   {
    instance.lang_=new String(e.nextRecord());
    r=true;
   }
   else
   {
    r=false;
   }
   rs.closeRecordStore();
  }
  catch(Exception ex)
  {
   r=false;
  }
  if(!r)
  {
   App.setCurrent(instance.new LanguageMenu());
  }
 }
 return r;
}

  程序管理器写完了,那么如何把他整合进MIDlet里面?看一下几个主要的函数就清楚了:

public TestSM()
{
 App.createInstance(this);
}

protected void startApp() throws MIDletStateChangeException {
 if(App.selectLanguage() && !App.restart())
 {
  start();
 }
}

public void start()
{
 SM.getInstance(App.getLanguage()).load("1");
 App.setCurrent(new TestCanvas());
}

protected void pauseApp() {
 App.pause();
}

  这回是大功告成了。总结一下他的优点:

  1、在需要返回前一屏的地方只需要一个App.restore();

  2、自动处理暂停和恢复;

  3、随时取得系统参数App.getProperty();

  4、统一的错误处理;

  5、整合多语言功能;

  6、更方便的切换屏幕,只需要App.setCurrent()。
  
 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:微软SQL Server 2005的30项顶尖特性
· 下一篇:ADO.NET 批量数据和多动态结果集
· Palm OS开发入门
· Windows XP操作系统中轻松查找MAC地址
· 组件编程之自定义属性编辑器的调试
· 软件也要时尚漂亮 软件包装周边制作一览
· AJAX.NET用户开发指南


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077