Header
Home | Sitemap Set as homepage | Add to favorites
  Search the Site     » Advanced Search
Sections



Timer Support

by

image

Timer Support

MIDlets may need to delay or schedule activities to be performed at a later time. The MIDP Specification provides two mechanisms to enable this:

The MIDP Specification provides two classes: Timer and TimerTask, that include functions for several types of timers. The general setup of a timer is illustrated next. In order to define a task to run, the programmer first defines a new timer task class by inheriting class TimerTask. The code to be executed by the timer is defined in the run method of the TimerTask subclass (see class MyTask below). In order to set up the actual timer, instances of class Timer and the new timer task class are created (objects myTimer and myTask in this example), and the schedule method of the timer object is then called with the task object and the appropriate time values as parameters. In this example, the timer will start executing in 10 milliseconds and will then repeat every 500 milliseconds.

class MyTask extends TimerTask {
public void run() {
...
}
}
...
myTimer = new Timer();
myTask = new MyTask();
myTimer.schedule(myTask, 10, 500);

There are two basic types of timers in MIDP: one-shot timers and repeating timers. The key difference between these two types of timers is the scheduling approach. A one-shot timer executes the specified task only once. A repeating timer continues executing the specified task repeatedly at a specific interval.

Timers can be used by a MIDlet in both the Active and Paused states, although use in the Paused state is discouraged.

20.1.1 Using One-Shot Timers

A one-shot timer can be set up to execute a task in two different ways. In the first approach, a java.util.Date object is passed into the schedule method of the Timer object. When the time specified by the Date object occurs, the timer task is run. If the Date passed in to the Timer object has already passed, then the timer task is run immediately. The following code fragment illustrates a timer whose task will be executed after 1000 milliseconds have passed after the current time (that is, after the time when the timer scheduling took place):[1]

[1] Keep in mind that MIDP Specification does not provide any real-time guarantees. There is no guarantee that the scheduled task would start exactly at the specified time. Usually, the scheduled tasks will start executing as soon as possible after the specified time.

myTimer.schedule(myTask,
new Date(System.currentTimeMillis() + 1000);

The second way to schedule a one-shot timer is by passing it a long value that contains the number of milliseconds to wait before executing the timer task. For instance, the following piece of code defines another timer whose task will be executed after 1000 milliseconds have passed:

myTimer.schedule(myTask, 1000);

20.1.2 Using Repeating Timers

The second type of timer supported by MIDP is a repeating timer. In this type of timer, the timer task is run repeatedly with a fixed period until the timer is canceled. Like one-shot timers, repeating timers can be set up to start executing the given task at a fixed time in the future (using a Date object as a parameter) or after a delay of a given number of milliseconds (using a long value as a parameter). In either case, the timer scheduling methods take an additional long parameter that indicates the repeat period of the timer. This period is interpreted either as a fixed-delay or a fixed-rate period, depending on whether the scheduling of the task is done using method schedule or scheduleAtFixedRate, respectively.

myTimer.schedule(myTask, 10, 500); // Fixed-delay repeating timer
myTimer.scheduleAtFixedRate(myTask, 10, 500); // Fixed-rate timer

In the fixed-delay case, each execution of the timer task is scheduled relative to the actual execution time of the previous timer task. If an execution is delayed for any reason, such as garbage collection or other background activity, subsequent executions will be delayed as well. This means that the execution of a fixed-delay timer may drift if, for example, the system is under a heavy execution load.

The fixed-rate case is different in that the execution of each timer task is scheduled relative to the scheduled execution time of the initial timer task. Thus, if an execution of a timer task is delayed for any reason, two or more executions will occur in rapid succession to "catch up" with the timer.

20.1.3 Sample Code (TimerMIDlet.java)

graphics/20inf01.gif

The following example illustrates the use of timers and timer tasks in more detail. In this example, two graphical gauges are created using the javax.microedition.lcdui APIs, and these gauges are incremented or decremented by timer tasks. (See the figure at left.) The MIDlet has two abstract commands attached: OK and EXIT. If the OK command is selected, then the state of the timers is changed from non-active to active, or from active to non-active, depending on the current state of the timers. The MIDlet will exit if the EXIT command is selected.

TimerMIDlet.java
package examples.timermidlet;

import java.lang.*;
import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

/**
* A simple class that shows an example of using a Timer and
* a TimerTask.
*
* This MIDlet creates two gauges. One gauge, gaugeOne,
* sets elements from low to high. The other, gaugeTwo,
* set elements from high to low. In effect, this has
* gaugeOne "going up," and gaugeTwo "going down."
*
* The two timers fire at different intervals.
*
* There are two commands on our form:
*
* OK: toggles whether the times are active or not.
* EXIT: exits the MIDlet.
*/

public class TimerMIDlet extends MIDlet implements CommandListener {
// number of elements in gauge
final private static int GAUGE_MAX = 10;

private boolean timersRunning; // tracks state of timers
private Display myDisplay; // handle to the display

private Gauge gaugeOne; // "going up" gauge
private Gauge gaugeTwo; // "going down" gauge

private Form myScreen; // form on which to
// place gauges
private Command cmdOK; // OK command
private Command cmdExit; // EXIT command

private Timer timer;
private MyTimerTask timerTaskOne;
private MyTimerTask timerTaskTwo;

/**
* Internal class that provides a TimerTask.
*/
private class MyTimerTask extends TimerTask {
private Gauge myGauge; // reference to gauge
private boolean goUp; // if true, go up
private int num; // number of times called

/**
* Public constructor: stores "direction" and a reference to
* a gauge.
*/
public MyTimerTask(Gauge g, boolean up) {
myGauge = g;
goUp = up;
}

/**
* As the timer fires, this method is invoked. Set gauge
* based on goUp
*/
public void run() {
num++;
myGauge.setValue(goUp ?
GAUGE_MAX -(num % GAUGE_MAX) :
num % GAUGE_MAX);
}
}

/**
* Public constructor: gets handle to display,
* creates form, gauges, and commands.
*/
public TimerMIDlet() {
myDisplay = Display.getDisplay(this);
myScreen = new Form("TimerMIDlet");
gaugeOne = new Gauge("Up Gauge",
false,
GAUGE_MAX,
0);
myScreen.append(gaugeOne);

gaugeTwo = new Gauge("Down Gauge",
false,
GAUGE_MAX,
GAUGE_MAX);
myScreen.append(gaugeTwo);

cmdOK = new Command("OK", Command.OK, 1);
cmdExit = new Command("Exit", Command.EXIT, 1);
myScreen.addCommand(cmdOK);
myScreen.addCommand(cmdExit);
myScreen.setCommandListener(this);
}

/**
* Changes the state of timers to/from active to/from
* not active.
*/
private void flipFlop() {
if (timersRunning) {
timerTaskOne.cancel();
timerTaskTwo.cancel();
timer.cancel();
timersRunning = false;
} else {
timer = new Timer();
timerTaskOne = new MyTimerTask(gaugeOne, false);
timerTaskTwo = new MyTimerTask(gaugeTwo, true);
timer.schedule(timerTaskOne, 0, 1000);
timer.schedule(timerTaskTwo, 0, 1500);
timersRunning = true;
}
}

/**
* Called by the system to start our MIDlet.
* @exception MIDletStateChangeException
*/
protected void startApp() throws MIDletStateChangeException {
myDisplay.setCurrent(myScreen);
flipFlop();
}


/**
* Called by the system to pause our MIDlet.
* No actions required by our MIDLet.
*/
protected void pauseApp() {}

/**
* Called by the system to end our MIDlet.
* No actions required by our MIDLet.
*/
protected void destroyApp(boolean unconditional) {}

/**
* Respond to command selections. Process two commands:
*
* OK: flip flop the timers to/from active
* EXIT: exit this MIDlet
*/
public void commandAction(Command c, Displayable d) {
if (c == cmdOK) {
flipFlop();
} else if (c == cmdExit) {
destroyApp(false);
notifyDestroyed();
}
}
}

708 times read

Related news

» Package java.util
by admin posted on Nov 17,2006
» MIDlets
by admin posted on Jul 07,2007
» The MIDlet State Model
by admin posted on Sep 26,2007
» MIDlet Program Structure
by admin posted on Sep 26,2007
» Sample Code (RMSMIDlet.java)
by admin posted on Jul 08,2007


More Top News
Cisco Wireless Networking
Most Popular
Featured Author