E2ME progress bar and thread model example analysis

xiaoxiao2021-03-06  19

In the J2ME's UI system, the UI operation is running in a separate thread. Often required programmers to return to the interface method in the API. That is to say non-blocking. You must turn on a separate thread to complete your custom complex work, such as the IO operation that may occlude occurs. If you don't communicate with users, tell the user threads that will appear very unfrieved. The user may perform other operations and disrupt the normal operation of the program. A simple way is to provide a progress bar so that users will wait for a while until the program runs out. In order to free the programmer from the front stage schedule to the background thread communication, concentrate on the development of the background thread, it is necessary to design a progress strip model.

It should be noted that there are a variety of forms:

Animated formal progress bar, only the program is running (self-maintenance)

The progress bar of the interactive interactive form, the background thread is constantly changing the progress bar in the program operation by calling the corresponding method of the progress bar.

The expression of the progress bar should be flexible, do not fix its implementation

The progress bar object is repeated

There are several cases of the progress recipient and the background thread:

Just put the progress bar painting on the screen, and after the background task is completed, jump to the successful picture by the background thread.

For canceled tasks, users can try the Cancel task by clicking on the progress bar, the background task should be canceled as soon as possible and jump to the failed picture.

For non-jumping tasks, users only wait patiently.

If the background thread runs failed, you should jump to the failed screen.

The progress bar design (front desk) In order to achieve the diversity of the performance of the progress bar, the first abstract interface:

ProgressobServer.java

Package com.favo.u;

Import javax.microedition.lcdui.display;

/ **

* @Author Favo

*

* This is an observer that is imperative, and this model is the advantage of this model.

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

* 2, support the interrupt task, because the background thread is unable to interrupt,

* So there is no necessary way to call back the background thread in the observer,

* If you support interrupt, you can let the background thread to query the observer's isstopped ()

* 3, can be said that the progress strip only puts his own painting on the screen, he doesn't care about the background thread.

* /

Public interface progressobserver {

/ **

* Reset progress bar

* /

Public void reset ();

/ **

* Set the maximum plan

* /

Public void setmax ();

/ *

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

* It is also constructed here and opens the painting thread (often used in the animation scroll bar)

* /

Public void show (Display Display);

/ **

* Scroll bars exit command, if the progress bar has opened its own thread for automatic update screen,

* (Commonly used in animated scroll bar), closes the animation thread here

* /

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; public void setPROMPT (String Prompt);

}

Every method is very late, I explain two points:

1) "2, support the interrupt task, because the background thread is unable to interrupt, so there is no need to call back the background thread in the observer. If you support it, you can let the background thread to query observations. ISSTOPPED () "

If you want to support the interruptable thread, you want to be of course, we want the user to press the button to call back a method of the background thread to stop the thread, and this method returns immediately (the user response of the UI before the UI cannot be blocked). But think detailed, threads cannot be forced to stop, and even if it can be forced to stop is not safe. So this method can only be able to return it by setting a flag and then returning immediately. Such words are closer coupled with the UI of the front desk. In this way, it is better to let the background thread to query the status of the UI. In this way, the UI does not care to maintain his status in the background.

2) If you want to implement an interactive Division UI, it is clear that this UI is self-maintained (that is, the UI has its own painting thread). In order to be able to achieve this, threads can be turned on in Show, and threads in EXIT. For interaction UI, you can simply ignore the exit method.

The following gives an interactive UI (non-self-maintained) implemented by Form and Gauge, the reader can look at the details, refer to him to design your own Canvas, or self-maintenance, etc.

ProgressGaugeui.java

Package com.favo.u;

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 GAGE_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)

{

// The parameter design here is a prompt

Current = (Current 1)% Gauge_levels;

Gauge.SetValue (Current * Gauge_max / gauge_levels);

IF (param1! = null && param1 installationof string) {

SetPrompt (String) Param1);

}

}

Public boolean isstoppable () {

Return stoppable;

}

Public void setStoppable (Boolean Stoppable) {

THIS.STOPPABLE = STOPPABLE;

IF (stoppable) {

F.Addcommand (Stopcmd);

} else {

f.RemovCommand (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);

}

}

Background thread design

The background thread makes the following content:

1) Implement our task Runtask ()

2) If the user interrupts the thread, then Runtask () will be jumped to the failed screen we specified.

3) Call Ui.exit in the end of us

We need to do:

1) Provide a front desk UI, providing a picture that fails, providing an instance of Display

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

3) In Runtask (), if the task fails, manual jump failure screen

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

5) Query the user if the user cancels in Runtask (), if the user cancels, it should be clear and easy to use. But there is also a disadvantage: if the user cancels the task, but this time the task is close to completion, or has been completed. The background thread will still display the user to cancel the task and will jump to the failed screen we specified. At this time, it will generate inconsistencies. In order to solve the entire problem, the programmer can call TaskComplete () in Runtask () to force the task. This will return the task success even if the user cancels the task. Of course, you can also follow the default behavioral characteristics with TaskComplete ().

Backgroundtask.java

Package com.favo.u;

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 DISPLAY 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 (Needlert) {

Display.Setcurrent (Alertscreen, Prescreen);

} else {

Display.setcurrent (PRESCREEN);

}

}

}

Poui.exit ();

}

}

/ *

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

* If the task needs to update the progress bar, call Pgui.UpdateProgress ("Progress Tips").

* Customary manual call taskcomplete () in this method to prevent users from being close to the task

* Cancel when completed

* /

Public Abstract void runtask ();

/ **

* This is a lazy way, when you construct the BackgroundTask object,

Calling this method directly,

* You can help you initialize the progress UI and display it. Post 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;

btask.start ();

}

Public ProgressobServer getProgressobserver () {

Return Poui;

}

Public void taskcomplete () {

GetProgressobServer (). setstopped (false);

}

}

how to use

1) Generate a Progressobserver object POUI

If you use the default, by calling ProgressGaugeui.GetInstance ();

2) Constructing the BackgroundTask object BKTASK, usually can be implemented with anonymous classes.

3) Initialize the POUI -> Set field -> Show your POUI -> Turn on the BKTASK thread.

The third step can be used to complete, by calling the static method

BackgroundTask.RunwithProgressGauge (bktask,

"Title", "Tips", can be paused, display);

One example below, see if you understand, and it will be used.

TestprogressGauge.java

Package com.favo.u;

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 imports 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 commandivity (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 Will Jump To The Main Form",

null, alerttype.error;

Alertscreen.SetTimeout (Alert.Forever);

Needalert = True;

// Do Something First

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 process screen

Press Compute

User cancels

Back to the previous screen

Press Compute

转载请注明原文地址:https://www.9cbs.com/read-42126.html

New Post(0)