|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net也不过3,4本书足以,这就是区别。FavoYangEmail:favoyang@yahoo.com接待交换
Keywords:线程化模子j2meUI计划
内容提纲:
本文是《j2me进度条与线程化模子》一文的续(今后简称原文,没看过的倡议看一下)。
会商了原文中利用的线程模子的不敷,并针对她的弱点提出了新的改善举措并给出了改善后的完成。因原文中UI部分有天真的扩大性,未作变动。
版权声明:
本文同时宣布在www.j2medev.com和我的Blog(blog.csdn.net/alikeboy)上,假如必要转载,有三个路子:1)接洽我并经我批准;2)和www.j2medev.com有转载文章互助协定的3)经由过程Rss聚合我的Blog。别的转载必要全文转发(包含文章的头部),不要断章取义。
注释:
前台UI怎样和背景线程交互
原文中模子,是一个前台的ProgressGaugeUI与背景线程有关的模子。如许计划的时分最年夜水平上的化简了通讯的庞大性,实践上是一种双方向的模子(由BackgroundTask向PGUI通讯)。依照这类形式的请求,程序员在OverrideBackgroundTask的runTask()办法时,有任务按期的往查训前台的PGUI的运转情形,并依据这类情形做出反应。如许这类形式完整信任背景线程,将是不是呼应用户cancel命令的权力交给了背景线程,假如背景线程堕入贫苦没有呼应了(好比会见一个很高贵的收集毗连),此时用户试图cancel也没有效,程序将会临时的逝世锁,直到背景线程偶然间往反省前台的形态。而且在实践情形中,究竟甚么时分往查询,多年夜的频次都是成绩。在代码段中过量的此类代码,会影响对一般的流程的了解。
从上面的这个按次图,能够看到这个详细流程:
我们必要一个办法,让我们可以强迫的停止Task。这个办法由背景线程本人供应,取名叫做cancel()。固然没有任何一个办法能够强制线程当即停止(已经有,由于平安性成绩而被作废)。以是cancel()办法常常经由过程封闭的资本(一个毗连,一个流等)来迫使runTask产生非常被中止,runTask有任务依据本人的商定捕获此类非常并当即加入。一图胜千言,让我们看看这类办法的流程。
很明显的,关头在于前台的线程对背景的线程举行了回调,如许就能够办理成绩了。可是新的成绩来了,如许做迫使我们将前台与背景线程严密的耦合在了一同(由于要回调嘛)。能不克不及既完成回调又制止前台UI与背景线程的严密耦合呢?
经由过程Cancelable接口下降耦合度
幸亏,我门能够使用接口来完成这一点。
先前的模子是如许的:
为了下降耦合,我们创建一个接口
publicinterfaceCancelable{
/**
*本办法非堵塞,应当当即前往(若有需要开启新的线程)
*别的应制止对此办法的反复挪用
*/
publicvoidcancel();
}
接上去在ProgressObserver到场对这个办法的撑持
publicinterfaceProgressObserver{
……
……
/**
*设置作废Task时回调的函数对象
*@paramco
*/
publicvoidsetCancelalbeObject(Cancelableco);
}
如许,就能够在用户按下作废按钮的时分,就能够举行对Cancelable.cancel()的回调。如许天真性年夜年夜加强了。
新代码
更新后的代码以下,除改用以上的模子外,还对部分的BUG举行了改正,变动的中央会用分歧的色彩暗示。具体的用法可拜见正文
/////////////////////////////////////////////////////////////////
Cancelable.java
packagecom.favo.ui;
/**
*@authorFavo
*
*TODOTochangethetemplateforthisgeneratedtypecommentgoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
publicinterfaceCancelable{
/**
*此办法非堵塞,应当当即前往(假如有需要开启新的线程)
*别的应制止对此办法的反复挪用
*/
publicvoidcancel();
}
ProgressObserver.java
/*
*Createdon2005-2-26
*
*TODOTochangethetemplateforthisgeneratedfilegoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
packagecom.favo.ui;
importjavax.microedition.lcdui.Display;
/**
*@authorFavo
*
*这是模仿SmartTicket制造的进度条察看者,这个模子的长处是
*1,低耦合度。你能够经由过程Form,Canvas等来完成这个接口
*2,可中止义务的撑持。是经由过程在外部设置flag并回调cancelObject的cancel()来完成的。背景线程能够经由过程查询这个flag从而晓得用户是不是中止过Task。
*/
publicinterfaceProgressObserver{
/**
*将进度条复位,次要为了反复使用进度条
*/
publicvoidreset();
/**
*将进度条的值为设置最年夜
*/
publicvoidsetMax();
/**
*将本人绘制在屏幕上,假如进度条要开启本身的线程用于主动更新画面,
*也在这里机关并开启绘画线程(经常使用于动画转动条)
*/
publicvoidshow(Displaydisplay);
/**
*假如进度条已经开启本身的线程用于主动更新画面,(经常使用于动画转动条),在这里封闭动画线程
*假如没有请疏忽此办法
*/
publicvoidexit();
/**
*更新进度条,参数恣意
*/
publicvoidupdateProgress(Objectparam1);
/**
*查询进度条是不是能够停息
*/
publicbooleanisStoppable();
/**
*设置进度条是不是能够停息
*@paramstoppable
*/
publicvoidsetStoppable(booleanstoppable);
/**
*查询用户是不是停息了义务
*@return
*/
publicbooleanisStopped();
/**
*设置义务停息标志
*/
publicvoidsetStopped(booleanstopped);
/**
*设置题目
*/
publicvoidsetTitle(Stringtitle);
/**
*设置提醒
*/
publicvoidsetPrompt(Stringprompt);
/**
*设置是不是作废Task时回调的函数对象
*@paramco
*/
publicvoidsetCancelalbeObject(Cancelableco);
}
ProgressGaugeUI.java
/*
*Createdon2005-2-26
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
packagecom.favo.ui;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Display;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.Form;
importjavax.microedition.lcdui.Gauge;
/**
*@authorFavo
*新版本的pgUI,次要是增添了canceltask的才能,经由过程回调CancelableObject的
*cancel办法完成。
*Preferences-Java-CodeStyle-CodeTemplates
*/
publicclassProgressGaugeUIimplementsProgressObserver,CommandListener{
privatestaticfinalintGAUGE_MAX=8;
privatestaticfinalintGAUGE_LEVELS=4;
privatestaticProgressGaugeUIpgUI;
privateFormf;
privateGaugegauge;
privateCommandstopCMD;
booleanstopped;
booleanstoppable;
intcurrent;
CancelablecancelableObject;
protectedProgressGaugeUI(){
f=newForm("");
gauge=newGauge("",false,GAUGE_MAX,0);
stopCMD=newCommand("Cancel",Command.STOP,10);
f.append(gauge);
f.setCommandListener(this);
}
publicstaticProgressGaugeUIgetInstance(){
if(pgUI==null){
returnnewProgressGaugeUI();
}
returnpgUI;
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#reset(java.lang.Object)
*/
publicvoidreset(){
current=0;
gauge.setValue(0);
stopped=false;
setStoppable(false);
setTitle("");
setPrompt("");
cancelableObject=null;
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#updateProgress(java.lang.Object)
*/
publicvoidupdateProgress(Objectparam1){
//TODOAuto-generatedmethodstub
current=(current+1)%GAUGE_LEVELS;
gauge.setValue(current*GAUGE_MAX/GAUGE_LEVELS);
if(param1!=null&¶m1instanceofString){
setPrompt((String)param1);
}
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#isStoppable()
*/
publicbooleanisStoppable(){
returnstoppable;
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#setStoppable(boolean)
*/
publicvoidsetStoppable(booleanstoppable){
this.stoppable=stoppable;
if(stoppable){
f.addCommand(stopCMD);
}else{
f.removeCommand(stopCMD);
}
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#isStopped()
*/
publicbooleanisStopped(){
//TODOAuto-generatedmethodstub
returnstopped;
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#setTitle(java.lang.String)
*/
publicvoidsetTitle(Stringtitle){
//TODOAuto-generatedmethodstub
f.setTitle(title);
}
/*
*(non-Javadoc)
*
*@seecom.favo.ui.ProgressObserver#setPrompt(java.lang.String)
*/
publicvoidsetPrompt(Stringprompt){
gauge.setLabel(prompt);
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command,
*javax.microedition.lcdui.Displayable)
*/
publicvoidcommandAction(Commandarg0,Displayablearg1){
if(arg0==stopCMD){
if(isStoppable())
if(!isStopped()){//包管仅被挪用一次
setStopped(true);
if(cancelableObject!=null)
cancelableObject.cancel();
}
else{
setPrompt("cantstop!");
}
}
}
/*(non-Javadoc)
*@seecom.favo.ui.ProgressObserver#show(javax.microedition.lcdui.Display)
*/
publicvoidshow(Displaydisplay){
display.setCurrent(f);
}
/*(non-Javadoc)
*@seecom.favo.ui.ProgressObserver#exit()
*/
publicvoidexit(){
cancelableObject=null;
}
/*(non-Javadoc)
*@seecom.favo.ui.ProgressObserver#setMax()
*/
publicvoidsetMax(){
gauge.setValue(GAUGE_MAX);
}
/*(non-Javadoc)
*@seecom.favo.ui.ProgressObserver#setStopped(boolean)
*/
publicvoidsetStopped(booleanstopped){
this.stopped=stopped;
}
publicvoidsetCancelalbeObject(Cancelableco){
this.cancelableObject=co;
}
}
BackgroundTask.java
/*
*Createdon2005-2-26
*
*TODOTochangethetemplateforthisgeneratedfilegoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
packagecom.favo.ui;
importjavax.microedition.lcdui.AlertType;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.Display;
importjavax.microedition.lcdui.Alert;
/**
*@authorFavo
*
*TODOTochangethetemplateforthisgeneratedtypecommentgotoWindow-
*Preferences-Java-CodeStyle-CodeTemplates
*/
publicabstractclassBackgroundTaskextendsThreadimplementsCancelable{
ProgressObserverpoUI;
protectedDisplayablepreScreen;
protectedbooleanneedAlert;
protectedAlertalertScreen;
privateDisplaydisplay;
/*
*
*/
publicBackgroundTask(ProgressObserverpoUI,Displayablepre,
Displaydisplay){
this.poUI=poUI;
this.preScreen=pre;
this.display=display;
this.needAlert=false;
}
/*
*(non-Javadoc)
*
*@seejava.lang.Thread#run()
*/
publicvoidrun(){
booleantaskComplete=false;
try{
taskComplete=runTask();
}catch(Exceptione){
Alertal=newAlert("undefineexception",e.getMessage(),null,
AlertType.ALARM);
al.setTimeout(Alert.FOREVER);
display.setCurrent(al);
}finally{
if(!taskComplete&&poUI.isStoppable()){
if(poUI.isStopped()){//假如用户中止了程序
if(needAlert){
display.setCurrent(alertScreen,preScreen);
}else{
display.setCurrent(preScreen);
}
}
}
poUI.exit();
}
}
/**
*须由用户界说的义务
*注重!!!
*义务假如乐成的运转,应当由此办法外部卖力跳转至乐成画面,并前往true.
*若义务运转失利,请设置needAlert(是不是必要警报),AlertScreen(警报画面),preScreen(跳转回的前一个详细屏幕)
*手动更新进度栏,请挪用pgUI.updateProgress().
*请确保当cancel()挪用时,此办法会当即加入,并前往false(假如由于非常跳出此函数是能够承受的举动).
*/
publicabstractbooleanrunTask();
/**
*这是一个偷懒的举措,当你机关好BackgroundTask对象后,间接挪用这个办法,能够匡助你初始化进度UI,并显现出来。以后启动你的义务线程
*/
publicstaticvoidrunWithProgressGauge(BackgroundTaskbtask,Stringtitle,
Stringprompt,booleanstoppable,Displaydisplay){
ProgressObserverpo=btask.getProgressObserver();
po.reset();
po.setStoppable(stoppable);
if(stoppable){
po.setCancelalbeObject(btask);
}
po.setTitle(title);
po.setPrompt(prompt);
po.show(display);
btask.start();
}
publicProgressObservergetProgressObserver(){
returnpoUI;
}
//作废了taskComplete办法,由于runTask已有了前往值
//
//publicvoidtaskComplete(){
//getProgressObserver().setStopped(false);
//}
}
TestProgressGauge.java
/*
*Createdon2005-2-26
*
*TODOTochangethetemplateforthisgeneratedfilegoto
*Window-Preferences-Java-CodeStyle-CodeTemplates
*/
packagecom.favo.ui;
importjavax.microedition.lcdui.Alert;
importjavax.microedition.lcdui.AlertType;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Display;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.Form;
importjavax.microedition.midlet.MIDlet;
importjavax.microedition.midlet.MIDletStateChangeException;
/**
*@authorFavo
*
*TODOTochangethetemplateforthisgeneratedtypecommentgotoWindow-
*Preferences-Java-CodeStyle-CodeTemplates
*/
publicclassTestProgressGaugeextendsMIDletimplementsCommandListener{
/**
*
*/
Displaydisplay;
CommandworkCmd;
CommandexitCmd;
Formf;
publicTestProgressGauge(){
super();
//TODOAuto-generatedconstructorstub
display=Display.getDisplay(this);
workCmd=newCommand("compute",Command.OK,10);
exitCmd=newCommand("exit",Command.EXIT,10);
f=newForm("Test");
f.setCommandListener(this);
f.addCommand(workCmd);
f.addCommand(exitCmd);
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.midlet.MIDlet#startApp()
*/
protectedvoidstartApp()throwsMIDletStateChangeException{
//TODOAuto-generatedmethodstub
display.setCurrent(f);
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.midlet.MIDlet#pauseApp()
*/
protectedvoidpauseApp(){
//TODOAuto-generatedmethodstub
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.midlet.MIDlet#destroyApp(boolean)
*/
protectedvoiddestroyApp(booleanarg0)throwsMIDletStateChangeException{
//TODOAuto-generatedmethodstub
}
/*
*(non-Javadoc)
*
*@seejavax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command,
*javax.microedition.lcdui.Displayable)
*/
publicvoidcommandAction(Commandarg0,Displayablearg1){
//TODOAuto-generatedmethodstub
if(arg0==workCmd){
ProgressObserverpoUI=ProgressGaugeUI.getInstance();
BackgroundTaskbkTask=newBackgroundTask(poUI,arg1,display){
publicbooleanrunTask(){
System.out.println("taskstart!");
alertScreen=newAlert(
"usercancel",
"youpressthecancelbuttonandthescreenwilljumptothemainForm",
null,AlertType.ERROR);
alertScreen.setTimeout(Alert.FOREVER);
needAlert=true;
//dosomethingfirst
getProgressObserver().updateProgress(null);//手动更新
try{
Thread.sleep(3000);
}catch(Exceptione){
e.printStackTrace();
returnfalse;
}
getProgressObserver().updateProgress("sleepd3s...");//手动更新
//作废了此处的手动查询点
//if(getProgressObserver().isStopped())
//return;
getProgressObserver().updateProgress(null);//手动更新
//dosomethingagain
try{
Thread.sleep(3000);
}catch(Exceptione){
e.printStackTrace();
returnfalse;
}
getProgressObserver().setMax();//手动更新
display.setCurrent(newForm("complete"));//跳转乐成画面
returntrue;
}
publicvoidcancel(){
this.interrupt();
}
};
BackgroundTask.runWithProgressGauge(bkTask,"Sleep6s",
"Sleepnow...",true,display);
}elseif(arg0==exitCmd){
try{
destroyApp(false);
}catch(MIDletStateChangeExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
notifyDestroyed();
}
}
}
/////////////////////////////////////////////////////////////////
Java编译的是字节码,跟C++相反,启动不够快,效率不够高,难以精确控制内存,但是优点是编程比C++容易,代码比较安全但是容易留下性能隐患,跨平台靠字节码在各个平台复制(一处编译到处调试) |
|