Repropted J2ME progress bar and threaded model

xiaoxiao2021-03-06  14

Repropted J2ME progress bar and threaded model

Author: FavoYang Email:

Favoyang@yahoo.com Welcome to exchange

KeyWords: threaded model J2ME UI design

Summary:

This article is the "J2Me Progress Bar and Thread Model" (hereinafter referred to as the original text, I haven't seen it).

The shortcomings of the thread model used in the original text are discussed, and new improvement methods are put forward and given improved implementation. Due to the flexible scalability of the UI in the original text, it is not changed.

Copyright Notice:

This article is also published

Www.j2medev.com and my blog (blog.9cbs.net/alikeboy), if you need to reprint, there are three ways: 1) Contact me and agree; 2) and www.j2medev.com has reprinting article cooperation agreements 3) Aggregate my blog through RSS. Also reprint requires a full text forwarding (including the head of the article), do not break chapter.

text:

How to interact with the background thread

The model in the original text is a model that the front desk's ProgressGaugeui and the background thread is not related. To make it designed to limit the complexity of communication, it is actually a single-directional model (communicated by BackgroundTask to PGUI). In accordance with this mode, the programmer is obligated to regularly interrogate the operation of the PGUI of the front desk in Override BackgroundTask's Runtask () method, and reflects it according to this situation. This mode is fully confident that the backend thread will be handed over to the background thread in response to the right of the user's Cancel command. If the background thread is in trouble, there is no response (such as accessing a very expensive network connection). The program will temporarily dead lock until the background thread has time to check the status of the front desk. And in the actual situation, when do you go to query, how much frequency is a problem. Excessive such code in the code segment will affect the understanding of normal processes.

From the following sequence diagram, you can see this specific process:

We need a way to overcome Task. This method is provided by the background thread, named Cancel (). Of course, there is no way to force the thread to end immediately (once it is canceled because of security issues). So the Cancel () method is often used by closing resources (a connection, a stream, etc.) to force Runtask to occur to be interrupted, and Runtask is obliged to capture such exceptions according to their own agreement and immediately exit. A picture wins thousands of words, let us see the process of this method.

Obviously, the key is that the thread of the front desk has been callbacks in the background thread, which can solve the problem. But the new problem is coming, so forcing us to closely couple the front desk with the background thread (because of the callback). Can you realize callbacks and avoid close coupling of the reception UI and the background thread?

Reduce coupling through the Cancelable interface

Fortunately, I can use the interface to achieve this.

The previous model is like this:

In order to reduce coupling, we build an interface

Public interface ca ZANCELABLE {

/ **

* This method is non-blocking, it should be returned immediately (if necessary to open a new thread)

* Furthermore, repeat calls to this method should be avoided

* /

Public void ca Zancel ();

}

Next in ProgressobServer join support for this method

Public Interface Progressobserver {...

......

/ **

* Set the function object when canceling Task

* @Param Co

* /

Public void setcancelalbeobebject (Cancelable Co);

}

In this way, you can make a callback to the cancelable.cancel () when the user presses the cancel button. This flexibility is greatly enhanced.

New code

The updated code is as follows, in addition to the above model, the partial bug is also corrected, and the change is represented by different colors. Detailed usage can be found

/

Cancelable.java

Package com.favo.u;

/ **

* @Author Favo

*

* Todo to change the Template for this generated Type Comment Go To to

* WINDOW - Preferences - Java - Code Style - Code Templates

* /

Public interface ca ZANCELABLE {

/ **

*

This method is non-blocking, should be returned immediately (if necessary, new thread)

*

In addition, repeat calls should be avoided

* /

Public void ca Zancel ();

}

ProgressobServer.java

/ *

* Created on 2005-2-26

*

* Todo to change the Template for this generated file go to to THERATED FILE Go TO

* WINDOW - Preferences - Java - Code Style - Code Templates

* /

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, can be interrupting the support of the task. It is achieved by setting Flag internally setting Flag and calling Cancelobject's Cancel (). The background thread can be queried by this FLAG to know if the user has interrupt Task.

* /

Public interface progressobserver {

/ **

* Reset the progress bar, mainly for repeated use of progress bar

* /

Public void reset ();

/ **

* Set the value of the progress bar to the maximum

* /

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) and DISPLAY;

/ **

* If the progress bar has opened its own thread for automatic update screen, (often used for animation scroll bar), closes the animation thread here

* If not, please ignore this method

* /

Public void exit ();

/ **

* Update progress bar, argument arbitrary

* /

Public void UpdateProgress (Object Param1);

/ **

* Query the progress bar can be suspended

* /

Public boolean isstoppable ();

/ **

* Set whether the progress bar can be suspended

* @Param Stoppable

* /

Public void setstoppable (Boolean Stoppable);

/ **

* Query if the user suspends the task

* @Return

* /

Public boolean isstopped (); / **

* Setting the task pause tag

* /

Public void setStopped (Boolean Stopped);

/ **

* Set the title

* /

Public void settitle;

/ **

* Settlement prompt

* /

Public void setPrompt (String Prompt);

/ **

* Set whether to cancel the function object when Task

* @Param Co

* /

Public void setcancelalbeobebject (Cancelable Co);

}

ProgressGaugeui.java

/ *

* Created on 2005-2-26

* WINDOW - Preferences - Java - Code Style - Code Templates

* /

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

* The new version of PGUI, mainly adding the ability of Cancel Task, by callback CancelableObject

* CANCEL method is implemented.

* 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;

Cancelable CancelableObject;

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;

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # reset (java.lang.object)

* /

Public void reset () {

CURRENT = 0;

Gauge.setValue (0);

STOPPED = FALSE;

SetStoppable (FALSE); SetTitle ("");

SetPrompt ("");

CancelableObject = NULL;

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # updateProgress (java.lang.object)

* /

Public void updateprogress (Object param1) {

// Todo auto-generated method stub

Current = (Current 1)% Gauge_levels;

Gauge.SetValue (Current * Gauge_max / gauge_levels);

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

SetPrompt (String) Param1);

}

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # isstoppable ()

* /

Public boolean isstoppable () {

Return stoppable;

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # setStoppable (Boolean)

* /

Public void setStoppable (Boolean Stoppable) {

THIS.STOPPABLE = STOPPABLE;

IF (stoppable) {

F.Addcommand (Stopcmd);

} else {

f.RemovCommand (stopcmd);

}

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # isstopped ()

* /

Public boolean isstopped () {

// Todo auto-generated method stub

Return stopped;

}

/ *

* (non-javadoc)

*

* @see com.favo.u.progressobserver # settitle (java.lang.string)

* /

Public void setTitle (String Title) {

// Todo auto-generated method stub

F.SetTitle (Title);

}

/ *

* (non-javadoc)

*

* @see com.favo.ui.progressobserver # setPrompt (java.lang.string)

* /

Public void setPrompt (string prompt) {

Gauge.setlabel (Prompt);

}

/ *

* (non-javadoc)

*

* @see javax.microedition.lcdui.commandlistener # command (javax.microedition.lcdui.command,

* Javax.microedition.lcdui.displayable)

* /

Public void commandivity (command arg0, displayable arg1) {

IF (arg0 == stopcmd) {

IF (ISSTOPPABLE ())

IF (! isstopped ()) {// guarantees that only calls

SetStopped (TRUE);

IF (CancelableObject! = NULL)

CancelableObject.cancel ();

Else {

SetPrompt ("can't stop!");

}

}

}

/ * (non-javadoc)

* @see com.favo.ui.progressobserver # show (javax.microedition.lcdui.display)

* /

Public void show (Display Display) {

Display.setcurrent (f);

}

/ * (non-javadoc)

* @see com.favo.ui.progressobserver # exit ()

* /

Public void exit () {

CancelableObject = NULL;

}

/ * (non-javadoc)

* @see com.favo.ui.progressobserver # setmax ()

* /

Public void setmax () {

Gauge.SetValue (Gauge_max);

}

/ * (non-javadoc)

* @see com.favo.ui.progressobserver # setstopped (boolean)

* /

Public void setStopped (Boolean Stopped) {

this.stopped = stopped;

}

Public void setcancelalbeobebject (cancelable co) {

THIS.CANCELABLEOBJECT = CO;

}

}

Backgroundtask.java

/ *

* Created on 2005-2-26

*

* Todo to change the Template for this generated file go to to THERATED FILE Go TO

* WINDOW - Preferences - Java - Code Style - Code Templates

* /

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

*

* Todo to change the template for this generated Type Comment Go to window -

* Preferences - Java - Code Style - Code Templates

* /

Public Abstract Class BackgroundTask Extends Thread IMPLEments Cancelable {

Progressobserver POUI;

Protected Displayable Prescreen DISPLAY

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;

}

/ *

* (non-javadoc)

*

* @see java.lang.thread # run () * /

Public void run () {

Boolean Taskcomplete = FALSE;

Try {

Taskcomplete = runtask ();

} catch (exception e) {

Alert Al = New Alert ("undefine exception", E.GETMESSAGE (), NULL,

Alerttype.alarm;

Al.SetTimeOut (Alert.Forever);

Display.SetCurrent (al);

} finally {

IF (! taskcomplete && poui.isstoppable ()) {

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

IF (Needlert) {

Display.Setcurrent (Alertscreen, Prescreen);

} else {

Display.setcurrent (PRESCREEN);

}

}

}

Poui.exit ();

}

}

/ **

*

Must defined by the user

*

note!!!

*

If the task is successful,

This method should be responsible for jump to the successful picture inside this method.

And return to TRUE.

*

If the task is running failed,

Please set Needalert.

Do you need alerts), Alertscreen

Alert screen), Prescreen

Jump back the previous specific screen)

*

To manually update the progress bar, call pgui.UpdateProgress ().

*

Please make sure when Cancel ()

When calling,

This method will quit immediately.

And return false

If this function is an acceptable behavior because an exception is jumped out).

* /

Public Abstract Boolean Runtask ();

/ **

* This is a lazy way. When you construct a BackgroundTask object, call 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);

IF (stoppable) {

Po.SetcanceLalbeObject (btask);

}

Po.Settitle (Title);

Po.SetPrompt (Prompt);

Po.Show;

btask.start ();

}

Public ProgressobServer getProgressobserver () {

Return Poui;

}

// Cancel the taskcomplete method, because Runtask has returned value

//

// public void taskcomplete () {

// getProgressobServer (). Setstopped (false);

//}

}

TestprogressGauge.java

/ *

* Created on 2005-2-26

*

* Todo to change the Template for this generated file go to to THERATED FILE Go TO

* WINDOW - Preferences - Java - Code Style - Code Templates

* /

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

*

* Todo to change the template for this generated Type Comment Go to window -

* Preferences - Java - Code Style - Code Templates

* /

Public Class TestProgressGauge Extends Midlet ImmmandListener {

/ **

*

* /

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

}

/ *

* (non-javadoc)

*

* @see javax.microedition.midlet.mIdlet # startapp ()

* /

Protected void startapp () throws midletStateChangeException {

// Todo auto-generated method stub

Display.setcurrent (f);

}

/ *

* (non-javadoc)

*

* @see javax.microedition.midlet.midlet # PauseApp ()

* /

protected void pauseapp () {

// Todo auto-generated method stub

}

/ *

* (non-javadoc)

*

* @see javax.microedition.midlet.midlet # destroyApp (boolean)

* /

Protected Void DestroyApp (Boolean Arg0) throws midletStateChangeException {

// Todo auto-generated method stub

}

/ *

* (non-javadoc)

*

* @see javax.microedition.lcdui.commandlistener # command (javax.microedition.lcdui.command,

* Javax.microedition.lcdui.displayable) * /

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 Boolean Runtask () {

System.out.Println ("Task Start!");

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); // Manually update

Try {

Thread.sleep (3000);

} catch (exception e) {

E.PrintStackTrace ();

Return False;

}

getProgressobserver (). UpdateProgress ("Sleepd 3s ..."); / / manual update

// Cancel the manual query point here

// if (getProgressobServer (). Isstopped ())

// Return;

getProgressobServer (). UpdateProgress (null); // Manually update

// Do Something Again

Try {

Thread.sleep (3000);

} catch (exception e) {

E.PrintStackTrace ();

Return False;

}

GetProgressobServer (). setmax (); / / manual update

Display.SetCurrent (New Form ("" ")); // Jump success picture

Return True;

}

Public void ca Zancel () {

this.interrupt ();

}

}

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 ();

}

}

}

/

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

New Post(0)