In Practice

Let's write our first test example that demonstrates the activity life cycle. We'll want to have some sort of output that displays which state changes have happened so far. We'll do this in two ways:

The sole UI component that the activity will display is a so-called TextView. It displays text—we've already used it implicitly for displaying each entry in our starter activity. Each time we enter a new state, we append a string to the TextView, which will display all the state changes that happened so far.

Since we won't be able to display the destruction event of our activity in the TextView, as it will vanish from the screen too fast, we also output all state changes to LogCat. We do this with the Log class, which provides a couple of static methods to append messages to LogCat.

Remember what we need to do to add a test activity to our test application. First, we define it in the manifest file in the form of an <activity> element, which is a child of the <application> element:

<activity android:label="Life Cycle Test" android:name=".LifeCycleTest"

android:configChanges="keyboardlkeyboardHiddenlorientation" />

Next we add a new Java class called LifeCycleTest to our com.badlogic.androidgames package. Finally we add the class name to the tests member of the AndroidBasicsStarter class we defined earlier (of course, we already have that in there from when we wrote the class for demonstration purposes). We'll have to repeat all these steps for any test activity we create in the following sections. For brevity, I won't mention those steps again. Also note that I didn't specify an orientation for the LifeCycleTest activity. In this example we can thus be either in landscape or portrait mode depending on the device orientation. I did this so you can see the effect on an orientation change on the life cycle (none, due to how we set the configChanges attribute). Listing 4-2 shows you the code of the entire activity.

Listing 4-2., Demonstrating the Activity Life Cycle package com.badlogic.androidgames;

import; import android.os.Bundle; import android.util.Log; import android.widget.TextView;

public class LifeCycleTest extends Activity {

StringBuilder builder = new StringBuilder();

TextView textView;

private void log(String text) { Log.d("LifeCycleTest", text); builder.append(text); builder.append('\n'); textView.setText(builder.toString());

^Override public void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState); textView = new TextView(this); textView.setText(builder.toString()); setContentView(textView); log("created");

^Override protected void onResume() { super.onResume(); log("resumed");

^Override protected void onPause() { super.onPause(); log("paused");

Let's go through this code real quick. The class derives from Activity—not a big surprise. We define two members: a StringBuilder, which will hold all the messages we have produced so far, and the TextView, which we use to display those messages directly in the Activity.

Next we define a little private helper method that will log text to LogCat, append it to our StringBuilder, and update the TextView text. For the LogCat output, we use the static Log.d() method, which takes a tag as the first argument and the actual message as the second argument.

In the onCreate() method, we call the superclass method first as always. We create the TextView and set it as the content view of our activity. It will fill the complete space of the activity. Finally we log the message created to LogCat and update the TextView text with our previously defined helper method log().

Next we override the onResume() method of the activity. As with any activity methods we override, we first call the superclass method. All we do is call log() again with resumed as the argument.

The overridden onPause() method looks much like the onResume() method. We log the message as "paused" first. We also want to know whether the activity is going to be destroyed after the onPause() method call, so we check the Activity.isFinishing() method. If it returns true, we log the finishing event as well. Of course, we won't be able to see the updated TextView text, as the activity will be destroyed before the change is displayed on the screen. Thus, we also output everything to LogCat, as discussed earlier.

Run the application and play around with this test activity a little. Here's a sequence of actions you could execute:

1. Start up the test activity from the starter activity.

2. Lock the screen.

3. Unlock the screen.

4. Press the home button (which will get you back to the home screen).

5. On the home screen, hold the home button until you are presented with the currently running applications. Select the Android Basics Starter app to resume (which will bring the test activity back onscreen).

6. Press the back button (which will bring you back to the starter activity).

If your system didn't decide to kill the activity silently at any point it was paused, you will see the output in Figure 4-4 (of course, only if you haven't pressed the back button yet).

Figure 4-4. Running the LifeCycleTest activity

On startup, onCreate() is called, followed by onResume(). When we lock the screen, onPause() is called. When we unlock the screen, onResume() is called. When we press the home button, onPause() is called. Going back to the activity will call onResume() again. The same messages are of course shown in LogCat, which you can observe in Eclipse in the LogCat view. Figure 4-5 shows what we wrote to LogCat while executing the preceding sequence of actions (plus pressing the back button).


LifeCycleTest pid tag Message

D 2243 LifeCycleTest created

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused pid tag Message

D 2243 LifeCycleTest created

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused

D 2243 LifeCycleTest resumed

D 2243 LifeCycleTest paused


Figure 4-5. The LogCat output of LifeCycleTest

Pressing the back button again invokes the onPause() method. As it also destroys the activity, the conditional in onPause() also gets triggered, informing us that this is the last we'll see from that activity.

And that was the activity life cycle, demystified and simplified four our game programming needs. We now can easily handle any pause and resume events, and are guaranteed to be notified when the activity is destroyed.

0 0

Post a comment