Android Activity的生命周期简单总结
这里的内容参考官方的文档,这篇文章的目的不是去总结Activity是如何启动,如何创造,以及暂停和销毁的,而是从实际开发中分析在Activity各个生命周期,我们应该处理的内容。
Activity 各个生命周期
由图可以看出 ,在一个activity的生命周期中,系统会像金字塔模型一样去调用一系列的生命周期回调函数。在最上端是当前Activity的运行状态,也就是说用户彻底看到这个Activity时,Activity正处于onResume()
状态。而且有图可以看出来存在很长时间的状态只有三个,Resume
, Paused
和Stoped
其他几个状态存在的时间比较短暂,很快就会进入其他状态。而Create
方法作为创建Activity时调用的方法,也是极为重要的回调方法。下面我们重点考虑这个四个方法的回调时机,并考虑在其中应该填入的功能。
onCreate
启动一个Activity,Android一般有2种方式,即通过点击主界面的应用图标启动Activity和在其他Activty中用startActivity
之类的方法启动新的Activity.但不管哪种方式,创建新的Activity时都会调用onCreate()
方法。我们必须来实现程序启动所需要的各种基本逻辑。比如声明UI元素,定义成员变量,配置UI等等。
注意在onCreate
里面尽量少做事情,避免程序启动太久看不到界面。因为onCreate
执行完事之后,用户并不能看到界面,直到经历了onStart
之后调用onResume
进入Resume状态,这时才是用户看到的界面,所以如何onCreate
中做的事情太多,则程序会启动的比较久。一般新建一个Activity会自动生成onCreate
,其代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
这里我们可以看到onCreate
回调方法中传入的参数是Bundle类型的savedInstanceState。这是参数是用来保存Activity和恢复Activity的。当Activity是因为用户点击Back按钮或者是activity通过调用finish()结束自己时,系统就丢失了对Activity实例的引用,因为这一行为意味着不再需要这个activity了。然而,如果因为系统资源紧张而导致Activity的Destory, 系统会在用户回到这个Activity时有这个Activity存在过的记录,系统会使用那些保存的记录数据(描述了当Activity被Destory时的状态)来重新创建一个新的Activity实例。那些被系统用来恢复之前状态而保存的数据被叫做 "instance state"
,它是一些存放在Bundle对象中的key-value pairs。这是官方对instance state的解释。一般,我们可以不用管它,因为他会自动保存每个View视图的信息,然后当恢复的时候,会自动恢复到之前的状态。但我们有时候也会让他保存一些我们希望他保存的东西,比如记录用户状态的成员变量信息,这时我们需要用到onSavaInstacneState()
方法,当用户离开Activity时,系统会调用它。当系统调用这个函数时,系统会在Activity被异常Destory时传递 Bundle 对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的onRestoreInstanceState()
方法与 onCreate() 方法中。
为了给Activity保存额外的状态信息,你必须实现onSaveInstanceState() 并增加key-value pairs到 Bundle 对象中,例如:
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);
}
然后恢复Activity的时候,我们先判断一下时候是第一次创建还是恢复之前被Destory
的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
}
...
}
我们也可以选择实现 onRestoreInstanceState()
,而不是在onCreate
方法里面恢复数据。 onRestoreInstanceState()
方法会在 onStart()
方法之后执行. 系统仅仅会在存在需要恢复的状态信息时才会调用 onRestoreInstanceState()
,因此不需要检查 Bundle 是否为null。
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);
}
onPause
Paused
状态是一个长期保持的静态状态,Activity有时候会被其他可见的组件阻塞,从而导致当前的activity进入Pause
状态。例如当打开一个对话框的时候,之前的 Activity会被暂停,但只要之前的Activity仍然被部分可见,这个activity就会会一直处于Paused
状态。然而,一旦之前的activity被完全阻塞并不可见时,则其会进入Stop
状态.activity一旦进入paused
状态,系统就会调用activity中的onPause()
方法, 该方法中可以停止不应该在暂停过程中执行的操作,如暂停视频播放;或者保存那些有可能需要长期保存的信息。如果用户从暂停状态回到当前activity,系统应该恢复那些数据并执行onResume()
方法。
通常在onPause()回调方法中做以下事情
停止动画或者是其他正在运行的操作,那些都会导致CPU的浪费.
提交在用户离开时期待保存的内容(例如邮件草稿).
释放系统资源,例如broadcast receivers, sensors (比如GPS), 或者是其他任何会影响到电量的资源。
例如, 如果程序使用Camera,onPause()
会是一个比较好的地方去做那些释放资源的操作。
@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;
}
}
不应该使用onPause()
来执行CPU-intensive 的工作,例如写数据到DB,因为它会导致切换到下一个activity变得缓慢。
onResume
当用户从Paused
状态恢复activity时,系统会调用onResume()
方法。请注意,系统每次调用这个方法时,activity都处于前台,包括第一次创建的时候。所以,应该实现onResume()
来初始化那些在onPause
方法里面释放掉的组件,并执行那些activity每次进入Resumed state
都需要的初始化动作 (例如开始动画与初始化那些只有在获取用户焦点时才需要的组件)
下面的onResume()
的例子是与上面的onPause()
例子相对应的。
@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
}
}
onStop
在下面一些关键的场景中会涉及到停止与重启:
用户打开最近使用app的菜单并从我们的app切换到另外一个app,这个时候我们的app是被停止的。如果用户通过手机主界面的启动程序图标或者最近使用程序的窗口回到我们的app,那么我们的activity会重启。
用户在我们的app里面执行启动一个新activity的操作,当前activity会在第二个activity被创建后stop。如果用户点击back按钮,第一个activtiy会被重启。
用户在使用我们的app时接收到一个来电通话.
Activity类提供了onStop()
与onRestart()
方法来允许在activity停止与重启时进行调用。不同于暂停状态的部分阻塞UI,停止状态是UI不再可见并且用户的焦点转移到另一个activity中.
在onStop
方法activity不再可见,并且应该释放那些不再需要的所有资源。一旦activity停止了,系统会在需要内存空间时摧毁它的实例(和栈结构有关,通常back操作会导致前一个activity被销毁)。极端情况下,系统会直接杀死我们的app进程,并不执行activity的onDestroy()
回调方法, 因此我们需要使用onStop()
来释放资源,从而避免内存泄漏。
上面我们已经说了在onPause()
中我们是不建议进行数据库读写等操作的,而应该把它放到onStop()
中,让该方法来执行一些CPU密集的操作。
就如同onResume
方法里来初始化被onPause
方法中关闭的资源,我们也应该在onStart
方法里来初始化在onStop
方法里关闭的资源。
当系统Destory我们的activity,它会为activity调用onDestroy()方法。因为我们会在onStop方法里面做释放资源的操作,那么onDestory方法则是我们最后去清除那些可能导致内存泄漏的地方。因此需要确保那些线程都被destroyed并且所有的操作都被停止。
至此,Activity生命周期中,我们应该做的工作就叙述完毕了。