官术网_书友最值得收藏!

Saving an activity's state

The mobile environment is very dynamic, with users changing tasks much more often than on desktops. With generally fewer resources on a mobile device, it should be expected that your application will be interrupted at some point. It's also very possible that the system will shut down your app completely to give additional resources to the task at hand. It's the nature of mobiles.

A user might start typing something in your app, be interrupted by a phone call, or switch over to another app to send a text message, and by the time they get back to your app, the system may have closed it down completely to free up the memory. To provide the best user experience, you need to expect such behavior and make it easier for your user to resume from where they left off. The good thing is that the Android OS makes this easier by providing callbacks to notify your app of state changes.

Note

Simply rotating your device will cause the OS to destroy and recreate your activity. This might seem a bit heavy-handed, but it's done for good reason—it's very common to have different layouts for portrait and landscape, so this ensures that your app is using the correct resources.

In this recipe, you'll see how to handle the onSaveInstanceState() and onRestoreInstanceState() callbacks to save your application's state. We will demonstrate this by creating a counter variable and increment it each time the Count button is pressed. We will also have an EditText and a TextView widget to see their default behavior.

Getting ready

Create a new project in Android Studio and name it StateSaver. We need only a single activity, so the autogenerated main activity is sufficient. However, we will need a few widgets, including EditText, Button, and TextView. Their layout (in activity_main.xml) will look like this:

<EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"/>

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="Count"
    android:onClick="onClickCounter"/>

<TextView
    android:id="@+id/textViewCounter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/button"/>

How to do it...

Perform the following set of steps:

  1. To keep track of the counter, we need to add a global variable to the project, along with a key for saving and restoring. Add the following code to the MainActivity.java class:
    static final String KEY_COUNTER = "COUNTER";
    private int mCounter=0;
  2. Then add the code needed to handle the button press; it increments the counter and displays the result in the TextView widget:
    public void onClickCounter(View view) {
        mCounter++;
        ((TextView)findViewById(R.id.textViewCounter)).setText("Counter: " + Integer.toString(mCounter));
    }
  3. To receive notifications of application state change, we need to add the onSaveInstanceState() and onRestoreInstanceState() methods to our application. Open MainActivity.java and add the following:
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_COUNTER,mCounter);
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mCounter=savedInstanceState.getInt(KEY_COUNTER);
    }
  4. Run the program and try changing the orientation to see how it behaves (if you're using the emulator, Ctrl + F11 will rotate the device).

How it works...

All activities go through multiple states during their lifetime. By setting up callbacks to handle the events, we can have our code save important information before the activity is destroyed.

Step 3 is where the actual saving and restoring occurs. The system sends a Bundle (a data object that also uses name/value pairs) to the methods. We use the onSaveInstanceState() callback to save the data and pull it out in the onRestoreInstanceState() callback.

But wait! Did you try typing text in the EditText view before rotating the device? If so, you'd have noticed that the text was also restored, but we don't have any code to handle that view. By default, the system will automatically save the state, provided it has a unique ID (not all views automatically have their state saved, such as the TextView, but we can manually save it if we want).

Tip

Note that if you want Android to automatically save and restore the state of a view, it must have a unique ID (specified with the android:id= attribute in the layout). Beware; not all view types automatically save and restore the state of a view.

There's more...

The onRestoreInstanceState() callback is not the only place where the state can be restored. Look at the signature of onCreate():

onCreate(Bundle savedInstanceState)

Both methods receive the same Bundle instance named savedInstanceState. You could move the restore code to the onCreate() method and it would work the same. But one catch is that the savedInstanceState bundle will be null if there is no data, such as during the initial creation of the activity. If you want to move the code from the onRestoreInstanceState() callback, just check to make sure that the data is not null, as follows:

if (savedInstanceState!=null) {
    mCounter = savedInstanceState.getInt(KEY_COUNTER);
}

See also

  • The Storing persistent activity data recipe will introduce persistent storage.
  • Take a look at Chapter 6, Working with Data, for more examples on Android activities.
  • The Understanding the activity lifecycle recipe explains the Android Activity Lifecycle.
主站蜘蛛池模板: 松桃| 武夷山市| 招远市| 康定县| 东港市| 盘锦市| 榆林市| 孝昌县| 郯城县| 斗六市| 灌云县| 青阳县| 林芝县| 福海县| 乡城县| 克什克腾旗| 牡丹江市| 垦利县| 武川县| 西藏| 晋城| 合山市| 威宁| 广德县| 安平县| 钟山县| 孟州市| 荥经县| 康乐县| 黑山县| 石阡县| 平顶山市| 西峡县| 拉孜县| 新闻| 枝江市| 永宁县| 溧阳市| 楚雄市| 平邑县| 南华县|