当前位置: 首页 > news >正文

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

作者:黑洞 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=895

这两天又研究了一下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,共同学习,共同提高:)

相关文章:

  • 深入学习之闭包和bind 原型重写
  • 浏览器的渲染过程
  • J2ME-定时器(TimerTask)使用及初探
  • 深入学习之改变this的方法
  • 使用J2MEUnit测试J2ME程序
  • 深入学习之图片预加载 和 闭包新认知
  • NetBeans 4.0创建J2ME手机RSS阅读器
  • J2ME游戏 之 NORMAL-FRAME
  • 深入学习之git操作
  • 开发NokiaS40系列应用程序初级篇
  • 深入学习之重写call方法
  • 深入学习之this 方法1
  • 基于Nokia S40的猜数字游戏之一
  • 深入学习之继承图总结
  • 基于Nokia S40的猜数字游戏之二
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • android图片蒙层
  • CentOS 7 防火墙操作
  • docker容器内的网络抓包
  • ES6 ...操作符
  • js
  • KMP算法及优化
  • Linux快速复制或删除大量小文件
  • npx命令介绍
  • Python进阶细节
  • rc-form之最单纯情况
  • Spark RDD学习: aggregate函数
  • SQLServer之创建数据库快照
  • vue学习系列(二)vue-cli
  • 大数据与云计算学习:数据分析(二)
  • 分享一份非常强势的Android面试题
  • 好的网址,关于.net 4.0 ,vs 2010
  • 开发基于以太坊智能合约的DApp
  • 排序(1):冒泡排序
  • 一、python与pycharm的安装
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • Android开发者必备:推荐一款助力开发的开源APP
  • raise 与 raise ... from 的区别
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (3)STL算法之搜索
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (四)Controller接口控制器详解(三)
  • (转载)从 Java 代码到 Java 堆
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • ***检测工具之RKHunter AIDE
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .net分布式压力测试工具(Beetle.DT)