這兩天又研究了一下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,共同學習,共同提高:)
(出處:http://www.49028c.com)
新聞熱點
疑難解答