The MIDlet Lifecycle
Mobile devices, whether emulators or real, interact with a MIDlet using their
own software, which is called Application Management Software (AMS).
A D V E R T I S E M E N T
The AMS is
responsible for initializing, starting, pausing, resuming, and destroying a
MIDlet. (Besides these services, AMS may be responsible for installing and
removing a MIDlet, as well.) To facilitate this management, a MIDlet can be in
one of three states which is controlled via the MIDlet class
methods, that every MIDlet extends and overrides. These states are active,
paused and destroyed.
Figure 10. The possible states of a MIDlet and the transition between them
As you can see from Figure 11, an installed MIDlet is put into a paused state
by the AMS creating an instance of it, by calling its no-args
constructor. This is of course, not the only way that the MIDlet can be in a
paused state. It can enter this state when the AMS calls the pauseApp()
method on an active MIDlet (and the method returns successfully). It can also
enter this state when the MIDlet pauses itself by calling the notifyPaused()
method, as opposed to the pauseApp() method, which is called by the
AMS. However, what exactly is happening with the MIDlet in the paused state?
In a paused state, the MIDlet is waiting for a chance to get into the active
state. Theoretically, in this state, it should not be holding or using any of
the device resources and should be passive in nature. Once the MIDlet is
created, this is the state to be in before becoming active. Also, entering the
paused state is necessary when the device requires it to consume fewer
resources, because these resources may be required for handling other device
functions, like handling an incoming call. This is when the device invokes the
pauseApp() method through the AMS. If the MIDlet should inform the
AMS that it has paused, it should invoke the notifyPaused() method,
which tells the AMS that the MIDlet has indeed paused.
One final way in which a MIDlet can get into a paused state is when the
MIDlet's startApp() method, which is called when the AMS invokes it
to start the MIDlet (either the first time or from a paused state), throws a
MIDletStateChangeException. Essentially, in case of an error, the
MIDlet takes the safe road of staying in the paused state.
The active state is where every MIDlet wants to be! This is when the MIDlet
can do its functions, hold the device resources and generally, do what it is
supposed to do. As said previously, a MIDlet is in an active state when the AMS
calls the startApp() method on a paused MIDlet (actually, the
MIDlet enters the active state just before this method is called by the
AMS). A paused MIDlet can request to go into the active state by calling the
method resumeRequest(), which informs the AMS that the MIDlet
wishes to become active. The AMS may of course, choose to ignore this request
or, alternatively, queue it if there are other MIDlets requesting the same.
The destroyed state is entered when a MIDlet's destroyApp(boolean
unconditional) method is called and returns successfully, either from an
active or paused state. This method is called by the AMS when it feels that
there is no need for the MIDlet to keep running and is the place the MIDlet may
perform cleanup and other last minute activities. The MIDlet can enter this
state itself, by calling the notifyDestroyed() method, which
informs the AMS that the MIDlet has cleaned up its resources and is eligible for
destruction. Of course, since in this case, the destroyApp(boolean
unconditional) method is not called by the AMS, any last-minute
activities must be done before this method is invoked.
What happens if the AMS calls the destroyApp(boolean unconditional)
method in the middle of an important step that the MIDlet may be doing, and may
be loath to be destroyed? This is where the Boolean unconditional
flag comes into the picture. If this flag is set to true, the MIDlet will be
destroyed, irrespective of what the MIDlet is doing. However, if this flag is
false, effectively, the AMS is telling the MIDlet that it wants the MIDlet to be
destroyed, but if the MIDlet is doing something important, it can raise a
MIDletStateChangeException, and the AMS will not destroy it just yet.
However, note that even then, there are no guarantees that the MIDlet will not
be destroyed, and it remains up to each device to decide how they should handle
the request. If the device does honor the MIDlet's request, it may try and
invoke the destroyApp(boolean unconditional) at a later stage.
Note that a destroyed state means that the MIDlet instance has been
destroyed, but not uninstalled from the device. The MIDlet remains installed in
the device, and a new instance of it may be created later.
Let me end this section, and this article, with a flow chart of a typical
sequence of events while using the DateTimeApp MIDlet that we created in the
previous sections, and the corresponding AMS actions and MIDlet states. This
flow chart is shown in Figure 11.
Figure 11. AMS actions and MIDlet states through a sequence of events
In the next part of this series, you will start creating useful MIDlets by
understanding the User Interface API of MIDP 2.0. This will allow you to create
powerful user interfaces, a key requirement for any MIDlet.