技术开发 频道

实战程序管理器和多语言程序

  【IT168 技术文档】这两天又研究了一下MIDlet程序的设计方法,发现通过写一个程序管理器可以大大方便MIDlet编程,并在这个基础上扩展了多语言支持。

  在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();   }

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

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

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

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

  4。统一的错误处理;

  5。整合多语言功能;

  6。更方便的切换屏幕,只需要App.setCurrent()。

  你还有更多的好主意吗?跟我分享一下如何?

  有意见或建议请联系vmlinuxx@gmail.com,共同学习,共同提高:)

0
相关文章