Activity生命周期
以下是学习官方文档关于Activity生命周期的笔记与心得。
Activity的生命周期是指在用户进行例如电话操作或者切换到其他应用时,当前app是否会崩溃,是否会保存用户的数据与进度,是否会占用有效系统资源等。
Basic info about Lifecycle Callbacks
下面是官方文档中给出的Activity生命周期的图解:
上述图中有三个最为重要的过程:
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的相关功能图:
我们可以看到,主要有两个方向,当程序在运行时,我们可以通过实现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);
}