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()。 |
|