Exploring Activity lifecycle

Every process running on the Android platform is placed on a stack. When you use an Activity in the foreground, the system process that hosts that Activity is placed at the top of the stack, and the previous process (the one hosting whatever Activity was previously in the foreground) is moved down one notch. This is a key point to understand. Android tries to keep processes running as long as it can, but it can't keep every process running forever because, after all, system resources are finite. So what happens when memory starts to run low or the CPU gets too busy? UNDERSTANDING HOW PROCESSES AND ACTIVITIES RELATE

When the Android platform decides it needs to reclaim resources, it goes through a series of steps to prune processes (and the activities they host). It decides which ones to get rid of based on a simple set of priorities:

1 The process hosting the foreground Activity is the most important.

2 Any process hosting a visible but not foreground Activity is next in line.

3 Any process hosting a background Activity is next in line.

4 Any process not hosting any Activity (or Service or BroadcastReceiver), known as an empty process, is last in line.

A very useful tool for development and debugging, especially in the context of process priority, is the Android Debug Bridge (adb), which you first met in chapter 1. You can see the state of all the running processes in the emulator by issuing the following command:

adb shell dumpsys activity

This command will output a lot of information about all the running processes, including the package name, PID, foreground or background status, the current priority, and more.

Because a user can elect to change directions at just about any time—make a phone call, change the screen orientation, respond to an SMS message, decide to stop using your wonderful stock market analysis application and start playing Android Poker—which in turn can affect overall system resources, all Activity classes have to be able to handle being stopped and shut down at any time. If the process your Activity is in falls out of the foreground, it is eligible to be killed (it's not up to you; it's up to the platform, based on resources and priorities).

To manage this environment, Android applications, and the Activity classes they host, have to be designed a bit differently than what you may be used to. Using a series of event-related callback type methods the Activity class defines, you can set up and tear down state gracefully. The Activity subclasses that you implement (as you saw a bit of with ReviewCriteria in the previous section) override a set of lifecycle methods to make this happen. As we discussed in section 3.1.1, every Activity has to implement the onCreate() method. This is the starting point of the lifecycle. In addition to onCreate(), most activities will also want to implement the onPause() method, where data and state can be persisted before the hosting process potentially falls out of scope.

The lifecycle methods that the Activity class provides are called in a specific order by the platform as it decides to create and kill processes. Because you, as an application developer, cannot control the processes, you have to rely on your use of the callback lifecycle methods to control state in your Activity classes as they come into the foreground, move into the background, and fall away altogether. This is a very significant, and clever, part of the overall Android platform. As the user makes choices, activities are created and paused in a defined order by the system as it starts and stops processes. ACTIVITY LIFECYCLE Beyond onCreate() and on-Pause(), Android provides other distinct stages, each of which is a part of a particular phase of the life of an Activity class. The most commonly encountered methods and the phases for each part of the lifecycle are shown in figure 3.3.

Each of the lifecycle methods Android provides has a distinct purpose, and each happens during part of the foreground, visible, or entire lifecycle phase.

onCreate()

Entire lifecycle onRestart() Visible phase onStart()

onDestroy()

Foreground phase onResume()

onPause()

Figure 3.3 Android Activity lifecycle diagram, showing the methods involved in the foreground and background phases

■ In the foreground phase, the Activity is viewable on the screen and on top of everything else (when the user is interacting with the Activity to per form a task).

■ In the visible phase, the Activity is on the screen, but it may not be on top and interacting with the user (when a dialog or floating window is on top of the Activity, for example).

■ The entire lifecycle phase refers to the methods that may be called when the application is not on the screen, before it is created, and after it is gone prior to being shut down.

Table 3.1 provides further information about the lifecycle phases and outlines the main high-level related methods on the Activity class.

Table 3.1 Android Activity main lifecycle methods and purpose

Method

Purpose

onCreate()

Called when the Activity is created. Setup is done here, Also provided is access to any previously stored state in the form of a Bundle.

onRestart()

Called if the Activity is being restarted, if it is still in the stack, rather than starting new.

onStart()

Called when the Activity is becoming visible on the screen to the user.

onResume()

Called when the Activity starts interacting with the user. (This is always called, whether starting or restarting.)

onPause()

Called when the Activity is pausing or reclaiming CPU and other resources. This method is where state should be saved so that when an Activity is restarted it can start from the same state it had when it quit.

onStop()

Called to stop the Activity and transition it to a nonvisible phase and subsequent lifecycle events.

onDestroy()

Called when an Activity is being completely removed from system memory. Happens either because onFinish() is directly invoked or the system decides to stop the Activity to free up resources.

Beyond the main high-level lifecycle methods outlined in table 3.1, there are further finer-grained methods that are available as well. Methods such as onPostCreate and onPostResume aren't normally needed, so we won't go into detail on them, but be aware that they exist if you need that level of control (see the Activity Javadoc for full method details).

As for the main lifecycle methods that you will use the majority of the time, it is very important to be aware that onPause() is the last opportunity you have to clean up and save state information. The processes that host your Activity classes will not be killed by the platform until after the onPause() method has completed, but they may be killed thereafter. This means the system will attempt to run through all of the lifecycle methods every time, but if resources are spiraling out of control (as determined by the platform), a fire alarm may be sounded and the processes that are hosting activities that are beyond the onPause() method may be killed at any point. Any time your Activity is moved to the background, onPause() is called. Before your Activity is completely removed, onDestroy() is not guaranteed to have been called (it probably will be called, under normal circumstances, but not always).

The onPause() method is definitely where you need to save persistent state. Whether that persistent state is specific to your application (such as user preferences) or global shared information (such as the contacts database), onPause() is where you need to make sure all the loose ends are tied up—every time. We will discuss how to save data in chapter 5, but here the important thing is to know when and where that needs to happen.

NOTE In addition to persistent state there is one more aspect you should be familiar with, and that is instance state. Instance state refers to the state of the UI itself. The onSave-InstanceState() Activity method is called when an Activity may be destroyed, so that at a future time the interface state can be restored. This method is used by the platform to handle the view state processing in the vast majority of cases. This means you normally don't have to mess with it. Nevertheless, it is important to know that it is there and that the Bundle it saves is handed back to the onCre-ate() method when an Activity is restored. If you need to customize the view state, you can, by overriding this method, but don't confuse this with the more common general lifecycle methods.

Managing activities with lifecycle events in this way, through parent processes the platform controls, allows Android to do the heavy lifting, deciding when things come into and out of scope, relieving applications of the burden themselves, and ensuring a level playing field. This is a key aspect of the platform that varies somewhat from many other application development environments. In order to build robust and responsive Android applications you have to pay careful attention to the lifecycle.

Now that we have some background in place concerning the Activity lifecycle and have created our first screen, we will next further investigate views and fill in some more detail.

0 0

Responses

Post a comment