J2ME progress bar and threading model

Source: Internet
Author: User
Tags abstract call back exit final implement sleep stub thread
J2ME progress bar and threading model
Author: Favoyang email:favoyang@yahoo.com Welcome to Exchange

Keyworld: Threading model J2ME UI Design



Content Summary:

This paper studies how to establish a user-friendly threading model, which consists of the foreground's progress bar UI and background threads in the background.



Copyright Notice:

This article at the same time published in Www.j2medev.com and my blog (blog.csdn.net/alikeboy), if necessary reprint, there are three ways: 1 contact me and by my consent; 2) and www.j2medev.com have reproduced article cooperation agreement 3 to aggregate my blog via RSS. Reproduced in addition to the need for full text forwarding (including the head of the article), not taken out of context.



Body:

Solve the problem
In the J2ME UI system, UI actions are run in a separate thread. Often in API Doc, programmers are required to return the interface method immediately. In other words, not blocked. You must open a separate thread to complete your custom complex work, such as networking and other blocking IO operations. If the new thread does not communicate with the user and tells the user that the thread is working, it will appear very unfriendly. The user may perform other actions to disrupt the normal operation of the program. An easy way to do this is to provide a progress bar so that the user will be willing to wait until the program runs out of results. In order to free the programmer from the foreground progress bar and the background thread communication, it is necessary to design a progress bar threading model to concentrate on the development of the background thread.



It should be noted that the progress bar has several forms:




A, animation form progress bar, only indicates that the program is running (self maintenance)

B, the interactive incremental form of the progress bar, the background thread by calling the progress bar of the corresponding method in the program running continuously change the status of the progress bar

C, the performance of the progress bar should be flexible, do not fix its implementation

D, progress bar objects to reuse



There are several situations in which the progress and background threads are communicated:

A, only the progress bar painting on the screen, and so after the background task is completed, the background thread to jump to the success of the screen.

B, for the task can be canceled, users can click the progress bar button to try Cancel task, background tasks should be canceled as soon as possible, and jump to the failure of the screen

C, for non-jump tasks, users only have to wait patiently

D, if the background thread fails to run, you should jump to the failed screen yourself



Design of the progress bar (front desk)
To achieve the diversity of the performance of the progress bar, first abstract an interface:

Progressobserver.java

Package com.favo.ui;

Import Javax.microedition.lcdui.Display;



/**

* @author Favo

*

* This is an observer of a progress bar modelled on Smart ticket, the advantage of which is

* 1, low coupling degree. You can implement this interface through Form,canvas, etc.

* 2, to support interruptible tasks, because the background thread is not mandatory to interrupt,

* So there is no need to recall the corresponding method of the background thread in the viewer,

* If support can be interrupted, you can let the background thread query the Observer's isstopped ()

* 3, you can say that the progress bar will only paint itself on the screen, he does not care about the background thread

*/

Public interface Progressobserver {

/**

* Reset the progress bar

*/

public void Reset ();



/**

* Set the progress bar to the maximum

*/

public void Setmax ();



/*

* Draw yourself on the screen, if the progress bar to open its own thread to automatically update the screen,

* Also constructs and opens painting threads here (often used for animated scroll bars)

*/

public void Show (display display);



/**

* scroll bar Exit command, if the progress bar once opened its own thread used to automatically update the screen,

* (often used for animated scroll bars), here to close the animation thread

*/

public void exit ();



/**

* Update progress bar

*/

public void UpdateProgress (Object param1);



public boolean isstoppable ();



public void Setstoppable (Boolean stoppable);



public boolean isstopped ();



public void setstopped (Boolean stopped);



public void Settitle (String title);



public void Setprompt (String prompt);

}



Every method is a scene, I explain two points:

1) "2, which supports interruptible tasks because the background thread is not mandatory, so there is no need to recall the corresponding method of the background thread in the viewer, and if support can be interrupted, let the background thread query the Observer's isstopped ()"

If you want to support a thread thread, take it for granted, we want a user to press the button to call back the background thread of a method to stop the threads, and this method to immediately return (the UI before the user response is not able to block). But think about it, the thread cannot be forced to stop, and even if it can be forced to stop is not safe. So this method can only be done by setting a flag and then returning immediately. This way, the thread is tightly coupled to the foreground UI. Instead, let the background thread query the state of the UI. The UI does not care who is in the background to maintain his state.



2 If you want to implement a non interactive animated UI, then obviously the UI is self maintained (that is, the UI has its own drawing thread alone). To achieve this, you can open a thread in show and end the thread in exit. For interactive UIs, you can simply ignore the exit method.



The following is an interactive UI (not self maintenance) implemented using form and gauge, where the reader can look at the details, referring to the different implementations that he can design for his own implementation with canvas, or self maintenance, etc.

Progressgaugeui.java

Package com.favo.ui;



Import Javax.microedition.lcdui.Command;

Import Javax.microedition.lcdui.CommandListener;

Import Javax.microedition.lcdui.Display;

Import javax.microedition.lcdui.Displayable;

Import Javax.microedition.lcdui.Form;

Import Javax.microedition.lcdui.Gauge;



/**

* @author Favo

* Preferences-java-code Style-code Templates

*/

public class Progressgaugeui implements Progressobserver, Commandlistener {



private static final int gauge_max = 8;



private static final int gauge_levels = 4;



private static Progressgaugeui Pgui;



Private Form F;



Private gauge gauge;



Private Command Stopcmd;



Boolean stopped;



Boolean stoppable;



int current;



Protected Progressgaugeui () {

f = new Form ("");

Gauge = new Gauge ("", False, Gauge_max, 0);

Stopcmd = new Command ("Cancel", Command.stop, 10);

F.append (gauge);

F.setcommandlistener (this);

}



public static Progressgaugeui getinstance () {

if (Pgui = = null) {

return new Progressgaugeui ();

}

return Pgui;

}



public void Reset () {

current=0;

Gauge.setvalue (0);

Stopped=false;

Setstoppable (FALSE);

Settitle ("");

Setprompt ("");

}



public void UpdateProgress (Object param1) {//Here the argument is designed as a prompt

Current= (current+1)%gauge_levels;

Gauge.setvalue (current * gauge_max/gauge_levels);

if (param1!=null && param1 instanceof String) {

Setprompt ((String) param1);

}

}



public Boolean isstoppable () {

return stoppable;

}



public void Setstoppable (Boolean stoppable) {

this.stoppable = stoppable;

if (stoppable) {

F.addcommand (Stopcmd);

}else{

F.removecommand (Stopcmd);

}

}



public Boolean isstopped () {

return stopped;

}



public void setstopped (Boolean stopped) {

this.stopped=stopped;

}



public void Settitle (String title) {

F.settitle (title);

}



public void Setprompt (String prompt) {

Gauge.setlabel (prompt);

}



public void Commandaction (Command arg0, displayable arg1) {

if (arg0==stopcmd) {

if (isstoppable ())

Stopped=true;

else{

Setprompt ("Can ' t stop!");

}

}

}



public void Show (display display) {

Display.setcurrent (f);

}

public void exit () {

Ignore

}

public void Setmax () {

Gauge.setvalue (Gauge_max);

}

}



Design of background threads
The background thread makes the following for us:

1) Perform our task Runtask ()

2 If the user is disconnected from the thread, then Runtask () after running, will jump to our specified failure screen

3) At the end of the call for US ui.exit ()



What we need to do is:

1 provides a foreground UI that provides a picture of the failed jump, providing an example of display

2 in Runtask (), if the task is completed, manual jump failed screen

3 in Runtask (), if the task fails, manual jump failed screen

4 Change the status of the progress bar in Runtask ().

5 in Runtask () query whether the user is canceled, if the user cancels, should exit Runtask as soon as possible ()



This model has clear responsibilities and is easy to use. But there is one drawback: if the user cancels the task, the task is nearing completion, or has been completed. The background thread will still show that the user canceled the task and will jump to the failed screen we specified. There is an inconsistency. To solve the whole problem, the programmer can call Taskcomplete () in Runtask () to force the task to complete. This shows that the task succeeds even if the user cancels the task. Of course you can't drop it. Use Taskcomplete () to follow the default behavior characteristics.



Backgroundtask.java

Package com.favo.ui;



Import Javax.microedition.lcdui.AlertType;

Import javax.microedition.lcdui.Displayable;

Import Javax.microedition.lcdui.Display;

Import Javax.microedition.lcdui.Alert;



/**

* @author Favo

* Preferences-java-code Style-code Templates

*/

Public abstract class Backgroundtask extends Thread {



Progressobserver Poui;



protected displayable prescreen;



protected Boolean Needalert;



protected Alert Alertscreen;



private display display;



Public Backgroundtask (Progressobserver Poui, displayable Pre,

Display display) {

This.poui = Poui;

This.prescreen = pre;

This.display = display;

This.needalert = false;

}



public void Run () {

try {

Runtask ();

catch (Exception e) {

Alert Al = new Alert ("Undefine exception",

E.getmessage (), NULL,

Alerttype.alarm);

Al.settimeout (Alert.forever);

Display.setcurrent (AL);

finally {

if (poui.isstoppable ()) {

if (poui.isstopped ()) {//If the user interrupts the program

if (Needalert) {

Display.setcurrent (Alertscreen, prescreen);

} else {

Display.setcurrent (Prescreen);

}

}

}

Poui.exit ();

}

}



/*

* If the task can be interrupted, view pgui.isstopped (). And exit this method as soon as possible;

* Call Pgui.updateprogress ("Progress hint") if the task needs to update the progress bar.

* The last manual invocation of this method is customary taskcomplete () to prevent the user from approaching the task

* Cancel when completed

*/

public abstract void Runtask ();



/**

* This is a lazy way, when you construct the Backgroundtask object, call this method directly, * can help you initialize the progress UI, and show it. And then start your task thread

*/

public static void Runwithprogressgauge (Backgroundtask btask, String title,

String prompt, Boolean stoppable, display display) {

Progressobserver po = btask.getprogressobserver ();

Po.reset ();

Po.setstoppable (stoppable);

Po.settitle (title);

Po.setprompt (prompt);

Po.show (display);

Btask.start ();

}



Public Progressobserver Getprogressobserver () {

return Poui;

}



public void Taskcomplete () {

Getprogressobserver (). setstopped (false);

}

}





How to use
1) produce a Progressobserver object Poui

If used by default, by calling Progressgaugeui.getinstance ();

2) constructs the Backgroundtask object Bktask, generally may use the anonymous class to realize.

3 Initialize the Poui--> setting after the field--> Show your poui--> to open the Bktask thread.

The third step can be done in one step by calling the static method

Backgroundtask.runwithprogressgauge (Bktask, "title",

"Prompt", whether can suspend, display);



Here's an example to see if you understand it and use it.

Testprogressgauge.java

Package com.favo.ui;



Import Javax.microedition.lcdui.Alert;

Import Javax.microedition.lcdui.AlertType;

Import Javax.microedition.lcdui.Command;

Import Javax.microedition.lcdui.CommandListener;

Import Javax.microedition.lcdui.Display;

Import javax.microedition.lcdui.Displayable;

Import Javax.microedition.lcdui.Form;

Import Javax.microedition.midlet.MIDlet;

Import javax.microedition.midlet.MIDletStateChangeException;



/**

* @author Favo

* Preferences-java-code Style-code Templates

*/

public class Testprogressgauge extends MIDlet implements Commandlistener {



Display display;



Command Workcmd;



Command Exitcmd;



Form F;



Public Testprogressgauge () {

Super ();

TODO auto-generated Constructor stub

display = Display.getdisplay (this);

Workcmd = new Command ("Compute", Command.ok, 10);

Exitcmd = new Command ("Exit", Command.exit, 10);

f = new Form ("Test");

F.setcommandlistener (this);

F.addcommand (Workcmd);

F.addcommand (Exitcmd);

}



protected void startApp () throws Midletstatechangeexception {

TODO auto-generated Method Stub

Display.setcurrent (f);

}



protected void Pauseapp () {

TODO auto-generated Method Stub



}



protected void Destroyapp (Boolean arg0) throws Midletstatechangeexception {

}



public void Commandaction (Command arg0, displayable arg1) {

TODO auto-generated Method Stub

if (arg0 = = Workcmd) {

Progressobserver Poui = Progressgaugeui.getinstance ();

Backgroundtask bktask = new Backgroundtask (Poui, arg1, display) {

public void Runtask () {

Alertscreen = new Alert (

"User Cancel",

"You press the Cancel button and the screen'll jump to the main Form",

NULL, ALERTTYPE.ERROR);

Alertscreen.settimeout (Alert.forever);

Needalert = true;

Do something

Getprogressobserver (). UpdateProgress (NULL);

try {

Thread.Sleep (3000);

catch (Exception e) {

E.printstacktrace ();

}

Getprogressobserver (). UpdateProgress ("SLEEPD 3s ...");

if (Getprogressobserver (). isstopped ())

Return

Getprogressobserver (). UpdateProgress (NULL);

Do something second

try {

Thread.Sleep (3000);

catch (Exception e) {

E.printstacktrace ();

}

Getprogressobserver (). Setmax ();

Display.setcurrent (New Form ("complete"));

Taskcomplete ();

}

};

Backgroundtask.runwithprogressgauge (Bktask, "Sleep 6s",

"Sleep now ...", true, display);

}else if (arg0==exitcmd) {

try {

Destroyapp (FALSE);

catch (Midletstatechangeexception e) {

TODO auto-generated Catch block

E.printstacktrace ();

}

Notifydestroyed ();

}

}



}

Run the process screen

Press the compute--> user to cancel-->



Back to the previous screen--> press compute-->



-->--> Complete



Hopefully, this model will speed up your development. If you have a better solution to a clearer solution to the problem or the details of the problem, welcome the discussion.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.