Support free tutorials

vogella training Training Books



Android application and activity life cycle - Tutorial

Lars Vogel

Version 1.3

09.02.2015

Understanding the Android lifecycle

This tutorial describes how the Android application and activity life cycle works.


Table of Contents

1. Managing the application life cycle
2. Application
3. Content provider life cycle
4. Activity life cycle
4.1. States of an activity
4.2. The live cycle methods
4.3. Termination of activities by Android
5. Activity instance state
6. Nonconfiguration instance scope
7. Controlling configuration
7.1. Avoiding configuration change restarts
7.2. Fixing the orientation for an activity
8. Exercise: Lifecycle
8.1. Target of this exercise
8.2. Create project
8.3. Create your activities
8.4. Testing
8.5. Instance state
9. About this website
9.1. Donate to support free tutorials
9.2. Questions and discussion
9.3. License for this tutorial and its code
10. Links and Literature
10.1. Source Code
10.2. Android ActionBar Resources
10.3. vogella Resources

1. Managing the application life cycle

In an ideal case all Android applications started by the user remain in memory, that makes restarting applications faster. But in reality the available memory on an Android device is limited. To manage these limited resources the Android system is allowed to terminate running processes or recycling Android components.

If the Android system needs to free up resources it follows a simple set of rules. Every process gets a priority in the following order.

If the Android system needs to terminate processes it follows the following priority system.

Table 1. Priorities

Process status Description Priority
Foreground An application in which the user is interacting with an activity, or which has an service which is bound to such an activity. Also if a service is executing one of its lifecycle methods or a broadcast receiver which runs its onReceive() method. 1
Visible User is not interacting with the activity, but the activity is still (partially) visible or the application has a service which is used by a inactive but visible activity. 2
Service Application with a running service which does not qualify for 1 or 2. 3
Background Application with only stopped activities and without a service or executing receiver. Android keeps them in a least recent used (LRU) list and if requires terminates the one which was least used. 4
Empty Application without any active components. 5


All processes in the "Empty" list are added to a least recently used list (LRU list) and the processes which are at the beginning of this lists are killed by the out-of-memory killer if required. If an application is restarted by the user its gets moved to the end of this queue if it reaches the lowest prio again, as indicated by the following graphic.

LRU list for process determination

2. Application

The application object is created whenever one of your Android components are started. It is started in a new process with a unique ID under a unique user. Even if you do not specify one in your AndroidManifest.xml file, the Android system creates a default object for you. This object provides the following main lifecycle methods:

  • onCreate() - called before the first components of the application starts

  • onLowMemory() - called when the Android system requests that the application cleans up memory

  • onTrimMemory() - called when the Android system requests that the application cleans up memory. This message includes an indicator in which position the application is. For example the constant TRIM_MEMORY_MODERATE indicates that the process is around the middle of the background LRU list; freeing memory can help the system keep other processes running later in the list for better overall performance.

  • onTerminate() - only for testing, not called in production

  • onConfigurationChanged() - called whenever the configuration changes

The application object starts before any component and runs at least as long as another component of the application runs.

3. Content provider life cycle

Once accessed a content provider is never stopped individually. It stops if the whole application process is determinted.

4. Activity life cycle

4.1. States of an activity

An activity can be in different states depending how it is interacting with the user. These states are described by the following table.

Table 2. Activity state

State Description
Running Activity is visible and interacts with the user.
Paused Activity is still visible but partially obscured, instance is running but might be killed by the system.
Stopped Activity is not visible, instance is running but might be killed by the system.
Killed Activity has been terminated by the system of by a call to its finish() method.


4.2. The live cycle methods

The Android system defines a life-cycle for activities via predefined life-cycle methods. The most important methods are:

Table 3. Important Activity lifecycle methods

Method Purpose
onCreate() Called then the activity is created. Used to initialize the activity, for example create the user interface.
onResume() Called if the activity get visible again and the user starts interacting with the activity again. Used to initialize fields, register listeners, bind to services, etc.
onPause() Called once another activity gets into the foreground. Always called before the activity is not visible anymore. Used to release resources or save application data. For example you unregister listeners, intent receivers, unbind from services or remove system service listeners.
onStop() Called once the activity is no longer visible. Time or CPU intensive shut-down operations, such as writing information to a database should be down in the onStop() method. This method is guaranteed to be called as of API 11.


The life cycle of an activity with its most important methods is displayed in the following diagram.

Activity life cycle

Android has more life cycle methods but not all of these methods are guaranteed to be called. The onDestroy() method is not guaranteed to be called, hence you typically do not use it.

For more information on the other methods see Activity life cycle - Official documentation.

4.3. Termination of activities by Android

The Android system is allowed to recycle Android activities to free up resources. In theory the Android system is allowed to terminate individual activities but in reality the Android system never recycles individual activities it always determines the whole process following the rules outlined in Section 1, “Managing the application life cycle”.

Note

It is a common misunderstanding that Android also kills individual activities, because the official life-cycle Android documentation describes this. However Dianne Hackborn from the core Android team involved in the out of memory killer implementation clarified on Stackoverflow that the Android system only kill processes and not individual activities. See Dianas Answer on Stackoverflow.

To ensure its state is saved, the activity needs to store the state of the activity at the right point in time and restore it. It should stop any unnecessary actions if the activity is not visible anymore to save system resources.

You typically use the onPause() method to stop framework listeners and UI updates and use the onStop() method to save the application data. These methods are guaranteed to be called before the activity is terminated. The onResume() is used to register again listeners and to trigger UI updates based on the saved data, if necessary.

In addition to resource management, Android also recreates activities in case a configuration change occurs. The Configuration object contains the current device configuration, if this configuration changes activities are restarted, as they may use different resources for this configuration.

5. Activity instance state

Instance state of an activity which is required to restore the activity to the state in which the user left it. This is non-persistent application data that needs to be passed between activities restarts during a configuration change to restore user selections. The application is responsible for restoring its instance state.

Assume for example the user scrolled through a ListView with thousands of items and the activity is recreated. Loosing the position in the list is annoying for the user, hence the position should be restored.

The onSaveInstanceState() can be used to store this instance state as a Bundle. A Bundle can contain primitive data types, arrays, String and objects which are of the Parcelable or Serialisable type.

The persisted Bundle data is passed at restart of the activity to the onCreate() method and onRestoreInstanceState() as parameter.

If you override onSaveInstanceState() and onRestoreInstanceState() you should call the super implementation of it, because the default views of Android store their data via a call to View.onSaveInstanceState from the onSaveInstanceState() method of the activity. For example EditText stores its content via the default call of this method.

The onRestoreInstanceState() or the onCreate() methods can be used to recreate the instance scope of an activity if it is restarted.

Tip

Prefer using the onRestoreInstanceState() method for restoring the instance state. This approach separates the initial setup from restoring the state.

If the user interacts with an activity and presses the Back button or if the finish() method of an activity is called, the activity is removed from the current activity stack and recycled. In this case there is no instance state to save and the onSaveInstanceState() method is not called.

If the user interacts with an activity and presses the Home button, the activity instance state must be saved. The onSaveInstanceState() method is called. If the user restarts the application it will resume or restart the last running activity. If it restarts the activity it provides the bundle with the save data to the onRestoreInstanceState() and onCreate() methods.

Warning

The onSaveInstanceState() method is not called if the user presses the back button. Don't use this approach to save the data which needs to get persisted.

6. Nonconfiguration instance scope

Nonconfiguration instance scope are Java objects which need to passed from one instance to the next instance of an activity in case of an configuration change.

Saving and restoring one object was possible with the getLastNonConfigurationInstance() and onRetainNonConfigurationInstance() methods. These methods have been deprecated, you should prefer using headless retained fragments for holding to objects which should be passed between activity instances due to configuration changes.

Warning

If you still using the approach of the onRetainNonConfigurationInstance() method, ensure that you are not passing objects to the next instance which have a reference to the current instance of the activity. Otherwise you have created a memory leak, i.e. the garbage collector cannot clean up the other instance of the activity as you are still holding on to a reference of it.

7. Controlling configuration

7.1. Avoiding configuration change restarts

An activity is restarted if a configuration change occurs. A configuration change happens if an event is triggered from the actual the Android device which may be relevant for the application.

An instance of the Configuration class defines the current configuration of the device. Typical configuration is the device orientation, the locale the smallest width, etc.

For example if the user changes the orientation of the device (vertically or horizontally). Android assumes that an activity might want to use different resources for these orientations and restarts the activity.

In case an activity is restarted the programmer must ensure that the activity is recreated in the same state as before the restart. The Android provides several potential means for doing this.

In the emulator you can simulate the change of the orientation via the Ctrl+F11 shortcut.

You can avoid a restart of your application for certain configuration changes via the configChanges attribute on your activity definition in your AndroidManifest.xml. The following setting avoids an activity restart incase of orientation changes or position of the physical keyboard (hidden / visible).

<activity android:name=".ProgressTestActivity"
     android:label="@string/app_name"
     android:configChanges="orientation|keyboardHidden|keyboard">
</activity> 

Tip

Avoid using the configChanges attribute if possible. It is typically better to use other means to handle configuration changes, like the Android loader framework or headless retained fragments. These concept are covered later.

7.2. Fixing the orientation for an activity

It is also possible to define that an activity should only be used in a specific screen orientation via the AndroidManifest.xml file. Such an example configuration is listed below.

<activity
   android:name="com.vogella.android.multitouch.MainActivity"
   android:label="@string/app_name"
   android:screenOrientation="landscape" >
   <intent-filter>
      <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity> 

8. Exercise: Lifecycle

8.1. Target of this exercise

In this exercise you create an application which allows you to observe the life cycle call of the Android system to your Android application.

8.2. Create project

Create a new project called com.vogella.android.lifecycle.activity.

Create the following class which is used to report lifecycle events via notifications.

package com.vogella.android.lifecycle.activity;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;

public class TracerActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    notify("onCreate");
  }

  @Override
  protected void onPause() {
    super.onPause();
    notify("onPause");
  }

  @Override
  protected void onResume() {
    super.onResume();
    notify("onResume");
  }

  @Override
  protected void onStop() {
    super.onStop();
    notify("onStop");
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    notify("onDestroy");
  }

  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    notify("onRestoreInstanceState");
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    notify("onSaveInstanceState");
  }

  private void notify(String methodName) {
    String name = this.getClass().getName();
    String[] strings = name.split("\\.");
    Notification noti = new Notification.Builder(this)
     .setContentTitle(methodName + " " + strings[strings.length - 1]).setAutoCancel(true)
     .setSmallIcon(R.drawable.ic_launcher)
     .setContentText(name).build();
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify((int) System.currentTimeMillis(), noti);
  }

} 

8.3. Create your activities

Create two activities which extend this one. The first activity should allow to start the second one via an Intent.

package com.vogella.android.lifecycle.activity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends TracerActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }

  public void onClick(View view) {
    Intent intent = new Intent(this, SecondActivity.class);
    startActivity(intent);
  }

} 

package com.vogella.android.lifecycle.activity;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class SecondActivity extends TracerActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
  }

  

} 

Warning

Ensure that both activities are registered in the Android manifest.

8.4. Testing

Start your application and trigger the second activity. Review the notifications and ensure you know why this order of things are happening.

Notifications about the lifecycle

Press the Back button on the second activity. Validate that onSaveInstanceState() is not called. Explain why it is not called.

Press the home button on the second activity. Validate that onSaveInstanceState() is called. Explain why it is called.

Start the second activity. Switch the orientation of your emulator via the CTRL+F11 shortcut and see which lifecycle methods of the activity are called. Is the first activity also re-created or only the second one?

Activate the Don't keep activities setting in the Developer Options. Test again which methods are called.

8.5. Instance state

Create a string array and add a Spinner view to your first activity using this array. The following lists the strings.xml and the layout file used by the first activity.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Lifecycle</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string-array name="operating_systems">
        <item >Ubuntu</item>
        <item >Android</item>
        <item >iOS</item>
    </string-array>

</resources> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="58dp"
        android:entries="@array/operating_systems" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:layout_gravity="bottom"
        android:text="Start new Activity" />

</LinearLayout> 

Android restores the state of a spinner automatically . Ensure that the selection of the spinner is saved and restored between configuration changes or restarts of the activity by the Android system.

Remove now the fixed array assignment in the layout and assign it to the Spinner via source code. .

// configure the spinner in code
Spinner spinner = (Spinner) findViewById(R.id.spinner);
String[] values = getResources().getStringArray(R.array.operating_systems);
ArrayAdapter<String> adapter = 
  new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values);
spinner.setAdapter(adapter); 

Remove the fixed assignment in your layout file.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="58dp"
        />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:layout_gravity="bottom"
        android:text="Start new Activity" />

</LinearLayout> 

Validate that in this case the position in the spinner is still automatically restored.

9. About this website

9.1. Donate to support free tutorials

Please consider a contribution Support free tutorials if this article helped you. It will help to maintain our content and our Open Source activities.

9.2. Questions and discussion

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

9.3. License for this tutorial and its code

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

10. Links and Literature

10.1. Source Code

Source Code of Examples

10.2. Android ActionBar Resources

Android Design Page

Android ActionBar Sherlock

10.3. vogella Resources

TRAINING SERVICE & SUPPORT
The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”. The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.