Android Basics – Managing Activity States – Part I
Managing and preserving an activity state is very important. If the activity state is not preserved properly, application can loose the data.
Using onSaveInstanceState():
Android provide two method onSaveInstanceState() and onRestoreInstanceState() to handle the activity state. onSaveInstanceState method gets called for an activity when user leaves the activity. Note this method is only called when activity is present in the History state and user can come back to the activity. Android provide a default implementation for this method. The default implementation save state of all the views which has id attribute defined. The default implementation of the onRestoreInstanceState() restores the state of the views. The bundle saved by the onSaveInstanceState() activity is passed to onCreate() and onRestoreInstanceState() methods both.
You can override the onSaveInstaceState method to save activity internal variable in the bundle. But do not forget to call the onSaveInstanceState method of the super class, otherwise handle the UI component state management your self.
Let’s create an example that clears the concepts
Example:
Here is the layout of the activity that ask user about it name and a secret
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" > <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name:" > </TextView> <EditText android:id="@+id/nameEditText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp" > </EditText> <TextView android:id="@+id/secretMessage" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Enter your Secret (I will not remember this):" > </TextView> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp" > </EditText> </LinearLayout>
Note that the editText for the secret message dose not have an Id attribute defined. The StateExampleActivity class looks like this
public class StateExampleActivity extends Activity {
/**
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.state_example_activity);
}
/**
* @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); // the UI component values are saved here.
Toast.makeText(this, "Activity state saved", Toast.LENGTH_LONG).show();
}
/**
* @see android.app.Activity#onDestroy()
*/
@Override
protected void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Activity is getting killed", Toast.LENGTH_LONG).show();
}
}
Our implementation of onSaveInstanceState() does not do much since the state of the views with Id is by default saved by the onSaveInstanceSate() method of super class.
Make the entry of the StateExampleActivity in the AndroidManifest.xml
<activity android:name="StateExampleActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Now start the application in the emulator. Put some data in the activity fields when activity is shown. Click on the Home button on the emulator. If only ‘Activity saved’ message is shown means the activity is not killed and the UI components does not loose their values. If you go back to the activity, you will be able to see values for both the text boxes name and secret text box.
To kill the activity when we leave it, android provided ‘Dev Tools’ can be used. Dev tools application can be opened from list of applications. Go to the Development Settings. You will see number of useful development settings. Check the ‘Immediately destroy activities’ check box. This will kill the activity after we left it.
Now run the application and follow the steps we followed earlier. Now after clicking the emulator home button the activity save and destroy message will be shown. If you reopen the activity now only user name value will be restored and secret will be lost.
Note if you click on the emulator BACK button the activity state will not be saved since the activity dose not go in the History stack. In that case the values for all the components will be lost.
Using state Bundle to save data:
Application can use activity’s state bundle to save data other than the UI component values, as shown
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("TO_REMEMBER", "Remember this"); // adding a string in bundle
Toast.makeText(this, "Activity state saved", Toast.LENGTH_LONG).show();
}
The saved value can be restored in onCreate method as follows:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.state_example_activity);
if (savedInstanceState != null) {
Toast.makeText(this, "onCreate() : " + savedInstanceState.getString("TO_REMEMBER"), Toast.LENGTH_LONG).show();
}
}
The state can be restored in onRestoreInstanceState() method too. Note that the onCreate() or onRestoreInstanceState() methods will only be called if the activity is killed.
As we saw the Android helps us to keep the state of the activity. But what if application wants to preserve the values even when user cancels the activity by using BACK button? That can be achieved with the help of preferences. We will see how to use preferences in second part of this post.