Activity生命周期

以下是学习官方文档关于Activity生命周期的笔记与心得。
Activity的生命周期是指在用户进行例如电话操作或者切换到其他应用时,当前app是否会崩溃,是否会保存用户的数据与进度,是否会占用有效系统资源等。

Basic info about Lifecycle Callbacks

下面是官方文档中给出的Activity生命周期的图解:

android glide 绑定生命周期 android生命周期的几个过程_文档

上述图中有三个最为重要的过程:
1. Resumed: 该状态表示activity在前台运行并且用户可以预与其进行交互,相当于线程中的running状态;
2. Paused: 暂停状态,该状态表示其他应用在前台但是不占据整个屏幕或者半透明,指定activity被其他应用影响,这种状态的activity不接受用户的输入以及执行任何代码。
3. Stopped: 停止状态,该状态表示指定activity被完全隐藏或者对用户不可见,它经常被视为在后台。一旦stopped,activity实例和它的状态信息(包括成员变量)会被保留,但是并不会执行任何代码。
4. 一般而言,一旦系统调用指定activity的onCreate()方法,它会迅速调用线程中的onStart()方法,紧随其后的是onResume()方法。

以上是生命周期的基本内容,下面来介绍一下特定的声明周期行为:

App’s launch activity

当用户点击主屏幕上的app图标时,该app就会执行onCreate方法,那么初始时显示的是哪一个activity呢?这时候就需要在manifests中进行设置了(默认状态为初始时的MainActivity):

<intent-filter>
     <action android:name="android.intent.action.MAIN" />
     <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

在intent-filter中的内容就是初始显示的activity。

Create a new instance

为了满足用户不同的行为需求,大多数的app都含多个activity,而他们都要实现onCreate()方法,去执行该activity的基础设置,例如定义UI、定义变量、配置UI等。
以下是一个实例:

TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set the user interface layout for this Activity
    // The layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);

    // Initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_message);

    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}

Destroy the Activity

虽然大多数apps中的activity在onPause()方法和onStop()方法中已经完成类大部分的内存清理任务,不需要去实现onDestroy()方法,但是如果你的app利用了后台线程,或者会造成内存泄漏现象,这时就需要onDestroy()方法去kill了。
以下是一个实例:

@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass

    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}

注意:一般而言在执行完了onPause()方法和onStop()方法之后系统才会调用onDestroy()方法,但是有一种情况除外:当我们在onCreate()方法中执行了finish()方法,那么不需要经过其他生命周期就会执行onDestroy()方法。

Pausing and Resuming an Activity

Pause Your Activity

正如之前所介绍到的,pause操作时一种中间态,会保存用户的数据,但是解除了CPU的占用。
以下是一个pause方法实现的实例:

@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release()
        mCamera = null;
    }
}

paused状态是部分可见状态(半透明或者屏幕一部分),当执行onStop()函数时会进入onStop()状态,当执行onResum()方法时又会重新进入running状态。

Resume Your Activity

以下就接着讲一下在paused状态之后调用onResume()方法的实例:

@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}

Stopping and Restarting an Activity

在以下几种情况下需要stop指定的activity:
1. 用户从当前app转换到了另外一个app;
2. 用户在你的app中执行了某一操作进入另外一个activity;
3. 用户在使用手机时接收到了电话。

Stop Your Activity

在对activity执行onStop()方法时,该activity会变得完全不可见,而且会进一步释放大量资源,解除CPU的暂用,但是仍然保留着内存数据。
以下是停止当前activity的实例:

@Override
protected void onStop() {
    super.onStop();  // Always call the superclass method first

    // Save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    ContentValues values = new ContentValues();
    values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
    values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

    getContentResolver().update(
            mUri,    // The URI for the note to update.
            values,  // The map of column names and new values to apply to them.
            null,    // No SELECT criteria are used.
            null     // No WHERE columns are used.
            );
}

Start/Restart Your Activity

在执行完onStop()方法之后,如果我们想要重新回到当前activity或者从其他应用回到当前应用,那么这个时候就需要使用onStart()方法,非特殊情况下一般不使用onRestart()方法。
以下是两种的程序实例:

@Override
protected void onStart() {
    super.onStart();  // Always call the superclass method first

    // The activity is either being restarted or started for the first time
    // so this is where we should make sure that GPS is enabled
    LocationManager locationManager = 
            (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

    if (!gpsEnabled) {
        // Create a dialog here that requests the user to enable GPS, and use an intent
        // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
        // to take the user to the Settings screen to enable GPS when they click "OK"
    }
}

@Override
protected void onRestart() {
    super.onRestart();  // Always call the superclass method first

    // Activity being restarted from stopped state    
}

Recreating an Activity

以下是重建一个Activity的相关功能图:

android glide 绑定生命周期 android生命周期的几个过程_数据_02


我们可以看到,主要有两个方向,当程序在运行时,我们可以通过实现onSaveInstanceState()方法来以键值对的形式保留用户数据,然后使当前activity进入Destroyed状态,另外就是当我们回到之前保存过数据的activity状态时,我们可以通过实现onRestoreIntanceState()方法使此activity进入运行状态。

Save Your Activity State

以下是存储当前activity状态数据的实例:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

Bundle总是以键值对的方式来进行用户数据的保存。

Restore Your Activity State

经过了先前的destroyed之后,当你的activity被重建时,你能够从Bundle恢复你的存储状态。onCreate()方法和onRestoreInstanceState()回调方法都可以通过接收相同的包含实例状态信息的Bundle实现。
由于onCreate()方法无论是创建一个新的activity还是重建先前的一个activity都会被调用,你必须在你试图去读取Bundle时检验Bundle是否为空。如果Bundle是空的,然后系统就可以创建一个新的activity实例,而不是存储先前destroyed的activity。
以下是使用onCreate()方法进行的实现:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

由于系统当且仅当存在一个将要被restore的状态时调用onRestoreInstanceState()方法,因此你不需要去检查Bundle是否为空。

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}