• No results found

Exploring the Activity lifecycle

User interfaces

3.1 Creating the Activity

3.1.2 Exploring the 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 concept 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?

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) is known as an empty process and is last in line.

A useful tool for development and debugging, especially in the context of process pri- ority, is the adb, which you first met in chapter 2. You can see the state of all the run- ning processes in an Android device or 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 pri- ority, and more.

All Activity classes have to be able to handle being stopped and shut down at any time. Remember, a user can and will change directions at will. It might be a phone call or an incoming SMS message, but the user will bounce around from one application to the next. If the process your Activity is in falls out of the foreground, it’s eligible to be killed and it’s not up to you; it’s up to the platform’s algorithm, based on avail- able resources and relative priorities.

The Builder pattern

You might have noticed the use of the Builder pattern, where we add parameters to the AlertDialog we created in the ReviewCriteria class. If you aren’t familiar with this approach, each of the methods invoked, such as AlertDialog.setMessage()

and AlertDialog.setTitle(), returns a reference to itself (this), which means we can continue chaining method calls. This approach avoids either an extra-long con- structor with many parameters or repeating the class reference throughout the code.

Intents also use this handy pattern; it’s something you’ll see time and time again in Android.

73

Creating the Activity

 The entire lifecycle phase refers to the methods that might be called when the application isn’t on the screen, before it’s created, and after it’s gone (prior to being shut down).

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

Beyond the main high-level lifecycle methods outlined in table 3.1, additional, finer- grained methods are available. You don’t typically need methods such as onPost- Create and onPostResume, so we won’t go into detail about them, but be aware that they exist if you need that level of control. See the Activity documentation for full method details.

As for the main lifecycle methods that you’ll use the majority of the time, it’s important to know that onPause() is the last opportunity you have to clean up and save state information. The processes that host your Activity classes won’t be killed by the platform until after the onPause() method has completed, but they might be killed thereafter. 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 plat- form, a fire alarm might be sounded and the processes that are hosting activities that are beyond the onPause() method might 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 called, though it might not be invoked in all circumstances.

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, Table 3.1 Android Activity main lifecycle methods and their 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’s still in the stack, rather than start- ing 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 method is always called, whether starting or restarting.)

onPause() Called when the Activity is pausing or reclaiming CPU and other resources. This method is where you should save state information so that when an Activity is restarted, it can start from the same state it was in 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. This method is called either because onFinish() is directly invoked or the system decides to stop the Activity to free up resources.

or globally 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’ll 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, you should be familiar with one more scenario: instance state. Instance state refers to the state of the UI itself. The onSaveInstanceState()method is called when an Activity might be destroyed, so that at a future time the interface state can be restored. This method is transparently used by the platform to handle the view state process- ing in the vast majority of cases; you don’t need to concern yourself with it under most circumstances. Nevertheless, it’s important to know that it’s there and that the Bundle it saves is handed back to the onCreate() method when an Activity is restored—as savedInstanceState in most code examples. If you need to customize the view state, you can do so by overriding this method, but don’t confuse this with the more common general lifecycle methods.

Managing activities with lifecycle events allows Android to do the heavy lifting, decid- ing when things come into and out of scope, relieving applications of the decision- making burden, and ensuring a level playing field for applications. This is a key aspect of the platform that varies somewhat from many other application development envi- ronments. To build robust and responsive Android applications, you have to pay care- ful attention to the lifecycle.

Now that you have some background about the Activity lifecycle and you’ve cre- ated your first screen, let’s investigate views and fill in some more detail.