Application Life Cycle

This overview describes the lifecycle of a BlackBerry® application. The lifecycle of an application refers to the possible states and transitions that an application can move through from the time it starts until it terminates.

BlackBerry devices support Java® ME compliant applications called MIDlets. MIDlets have a different application lifecycle that this overview will not cover. There are many web resources available that cover the MIDlet lifecycle.

The lifecycle of a BlackBerry application is simple. It starts, runs and terminates. During the running state, most applications receive and process events and update their UI accordingly.

The BlackBerry operating environment is multi-threaded. It enables you to run multiple applications simultaneously. It supports broadcasting events to multiple applications and running background threads.

BlackBerry Applications

It helps to understand how BlackBerry applications are structured and managed to understand their lifecycle. Applications are comprised of one or more code modules. Code modules are stored in files with the .cod file extension. Although an application can have just a single code module, many applications are implemented in a group of code modules. Code modules groups can have associated application metadata like vendor name and application version number.

You can work with individual code modules by using the CodeModuleManager class. To work with code module groups, use CodeModuleGroup and CodeModuleGroupManager.

All applications have an application class derived from either Application or UiApplication. If you want an application with a UI, then your application should extend UiApplication. Otherwise, your application should extend Application.

Starting

A BlackBerry application can be started in a number of ways:

Regardless of how an application is started, the Application Manager is responsible for starting the process the application will run within.

The ApplicationManager class enables applications to interact with the Application Manager to perform tasks, including:

Entry points

The Application Manager starts an application by getting a new process and spawning a thread within that process to call one of the entry points of the application. For many applications, the main() method of its application class is the single entry point that is called. But you can configure more than one entry point for an application.

Using more than one entry point lets you create different ways for a user to start an application. For example, if your application allows users to create a new document, you might like to provide users with two icons that they can click to start the application. Users could click one icon to open the application to its home screen and the other icon to open the application to the screen required to create a new document.

Application descriptors

Application descriptors are sets of data about an application. A single application can have more than one associated application descriptor. An application that has multiple entry points, for example, has an application descriptor corresponding to each of those entry points. You can use the ApplicationDescriptor class to work with application descriptors.

Click for code sample: List properties of applications

import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.MainScreen;


public class ListApplications extends UiApplication 
{
	StringBuffer strTmp = new StringBuffer();
	public static void main(String[] Args)
	{
		ListApplications app = new ListApplications();
		app.enterEventDispatcher();
	}
	public ListApplications()
	{
		ApplicationManager appMgr = ApplicationManager.getApplicationManager();
		ApplicationDescriptor[] ad = appMgr.getVisibleApplications();
		
		for(int i=0;i<ad.length;i++)
		{
			strTmp.append("Name: ");
			strTmp.append(ad[i].getName());
			strTmp.append('\n');
			strTmp.append("Module Name: ");
			strTmp.append(ad[i].getModuleName());
			strTmp.append('\n');
			strTmp.append("Version: ");
			strTmp.append(ad[i].getVersion());
			strTmp.append('\n');
			strTmp.append('\n');
		}
		this.pushScreen(new InfoScreen(strTmp.toString()));
	}
}

class InfoScreen extends MainScreen
{
	public InfoScreen(String strMsg)
	{
		RichTextField lf = new RichTextField(strMsg);
		add(lf);
	}
}

Running

Once the Application Manager starts an application, the application can either run a series of commands until it completes or it can enter a loop and wait for and process events until it receives an event that indicates it should terminate.

Each application has, associated with it, a special thread called the event thread. The event thread is the thread that has the event lock. It is the only thread that can process incoming events and it is the only thread that can update the UI of its associated application.

Typically, an application calls Application.enterEventDispatcher() somewhere near the beginning of its main() function. The result is that the thread that started the application by entering main(), acquires the event lock, becoming the event thread.

public class MyApplication extends Application
{
    // Entry point for the app
    public static void main(String[] args)
    {
         MyApplication thisApp = new MyApplication();
         thisApp.enterEventDispatcher();
    }
 
    /** Create a new MyApplication instance. */
    public MyApplication()
    {
        // ... Application's start-up work done here when
        // ... entry point instantiates this class.
    }
}

From that point onwards, the application is in an event processing loop. Any listeners you write and register - or are provided for you by the application framework - are called by the event thread in response to corresponding incoming messages.

Warning: Because the event thread is the only thread that can process events and update the UI of the application, you have to be extremely careful not to use it to run instructions that could fail or take a long time to complete. If, for instance, you need to make a network connection, you must spawn and use another thread.

To practice working with threads and updating the UI, see the Working with Multiple Processes and Threads section of the developer labs available on the BlackBerry® Developer Zone.

You may encounter situations where you want to update the UI from a non-event thread. There are two ways you can do that. You can acquire and synchronize on the event lock, causing your thread to act like the event thread or you can inject a event in the message queue of your application.

Synchronize on the event lock if you need to perform a quick or urgent UI update. Inject an event in the message queue if it is acceptable to experience a delay before your task runs. In either case, you should not run tasks that might take a long time to complete or might block. If you use library calls within your task, be sure you understand them well and only use them if they will finish quickly and do not block.

You inject an event in the form of an object that implements Runnable. The event is handled by the event thread as it is received from the message queue. The event thread processes the event by calling its run() method.

To inject runnable events in the message queue of your application, use one of the following methods: invokeAndWait() or invokeLater().

If you decide to synchronize on the event lock, you must quickly complete the UI update you require and release the lock. Otherwise, your application will become unresponsive and might eventually be terminated by the system. You acquire the event lock by calling Application.getEventLock().

Terminating

You can invoke System.exit() to terminate an application. This causes the BlackBerry® Java Virtual Machine to terminate all of the processes of the caller and, as a result, all associated threads. Alternatively, you can terminate an application by popping the last screen off the display stack, which results in the close() method making a call to System.exit().

Note: that it is good practice to manually deregister any listeners you registered before terminating your application.

Because you will typically start the event dispatcher thread by calling Application.enterEventDispatcher(), which doesn't terminate, your application should provide a way to terminate. Applications that interact with the user could provide a handler for a Close menu item and applications that do not interact with the user might terminate upon handling some system event that represents their reason for existence.


Copyright 1999-2010 Research In Motion Limited. 295 Phillip Street, Waterloo, Ontario, Canada, N2L 3W8. All Rights Reserved.
Copyright 1993-2003 Sun Microsystems, Inc. 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
Copyright 2002-2003 Nokia Corporation All Rights Reserved.
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.