应用程序(或Activity)执行的状态称为进程(progress)。在 Android操作系统中,每个应用程序都是一个进程。Android框架会维护一个唯一的Activity历史记录堆栈,并观察每个应用程序进程。同时,系统平台会依照系统的内存使用情况和Activity的状态来管理系统内存。Activity类别除了负责运行程序流程与操作系统界面组件外,最重要的就是它提供了开发者控制进程生命周期的函数。
Android应用程序的生命周期是由Android框架进行管理的,而不是由应用程序自己直接控制。通常每一个应用程序(入口一般会是一个Activity的onCreate方法),都会占据一个进程。当系统内存即将不足时,会依照优先级顺序自动进行进程的回收。
一个Activity类除了onCreate方法外,还预先定义了onPause(暂停进程时的行为)、onResume(继续进程的行为)等基本行为。当从一个Activity切换到另外一个Activity的时候,原本的Activity将经过一连串的状态改变。我们就可以在程序中添加一些各种状态相对应的流程,每次Activity改变状态时,就会执行相应的流程。
Activity的状态
Android的虚拟机是使用堆栈(Stack based)管理。主要有4种状态:
- Active(活动)
- Paused(暂停)
- Stopped(停止)
- Dead(已回收或未启动)
Active(活动)
Active状态是用户启动应用程序或Activity后,Activity运行中的状态。
在Android平台上,同一个时刻只会有一个Activity处于活动(Activity)或运行(Running)状态。其他的Activity都处于未启动(Dead)、停止(Stopped)或是暂停(Paused)状态。
Paused(暂停)
Paused状态是目前运行的屏幕画面暂时暗下来,退到背景画面的状态。
当我们使用“Toast”、“AlertDialog”或者来电话时,都会让原本运行的Activity退回为背景画面。新出现的“Toast”、 “AlertDialog”等界面组件盖住了原来的Activity界面。Activity处于Paused状态时,用户是无法与原Activity互动的。
Stopped(停止)
Stopped状态是有其他Activity正在执行,而这个Activity已经离开屏幕,不再有进行中的状态。
通过长按“主页”键,可以调出所有处于Stopped状态的应用程序。在Stopped状态的Activity,还可以通过“Notification”来唤醒。
Dead(已回收或未启动)
Dead状态是Activity尚未被启动或者被手动停止,或已经被系统自动回收的状态。
要手动终止Activity,可以在程序中调用finish()函数。如果是被系统自动回收,则表明可能是系统内存不足了,所以系统根据内存不足的回收规则,将处于Stopped状态的Activity所占用的内存回收。
系统内存不足时的行为
当Android系统内存不足时,会根据以下的规则来回收内存:
- 先回收与其他Activity或Service/Intent Receiver无关的进程,即优先回收独立的Activity
- 再回收处于Stopped状态的其他类型的Activity(在背景等待的Activity)。最久没有使用的Activity会被优先回收(比较官方的说法是根据“LRU算法”)
- 还不够?回收service进程
- 还不行?关掉可见的Activity/进程
- 关闭当前的Activity
当系统内存缺失到要关闭“可见的Activity/进程”时,那么是不是要考虑下换个手机了。
观察Activity运行流程
public class Bmi extends Activity { private static final String TAG = "Bmi"; public void onCreate() { super.onCreate(...); Log.v(TAG,"onCreate"); } public void onStart() { super.onStart(); Log.v(TAG, "onStart"); } public void onResume() { super.onResume(); Log.v(TAG, "onResume"); } public void onPause() { super.onPause(); Log.v(TAG, "onPause"); } public void onStop() { super.onStop(); Log.v(TAG, "onStop"); } public void onRestart() { super.onRestart(); Log.v(TAG, "onReStart"); } public void onDestroy() { super.onDestroy(); Log.v(TAG, "onDestroy"); } }
上面的七个状态又可以归纳成三组:
1. 资源分配(Create/Destroy)
完整的Activity 生命周期由”Create”状态开始,由”Destroy”状态结束。建立 (Create)时分配资源,销毁(Destroy)时释放资源。
2. 可见与不可见(Start/ReStart/Stop)
当Activity 运行到”Start”状态时,就可以在屏幕上看到这个Activity。相反地,当 Activity 运行到”Stop”状态时,这个Activity 就会从屏幕上消失。
当使用者按下Back 按钮回到上一个Activity 时,会先到Restart 状态,再到一般 的Start 状态。
3. 使用者能否直接存取屏幕(Resume/Pause)
当有个Toast、AlertDialog、简讯、电话等讯息乱入时,原来的Activity 会进入 “Pause”状态,暂时放弃直接存取屏幕的能力,被中断到背景去,将前景交给优先级高的事件。当这些优先级高的事件处理完后,Activity就改进入”Resume”状态,此时又直接存取 屏幕。
实际函数名称中都冠以On开头命名的方法,Activity的生命周期状态图如下:
Activity运作流程
由实际运行的记录来看,我们可以归纳出所有Android 应用程序都遵循的动作流程:
一般启动
- onCreate -> onStart -> onResume
启动一个Activity 的基本流程是:分配资源给这个Activity(Create状态),然后将Activity内容显示到屏幕上(Start状态)。在一切就绪后,取得屏幕的控制权(Resume状态),使用者可以开始使用这个程序。
调用另一个Activity
- onPause(1) -> onCreate(2) -> onStart(2) - onResume(2) -> onStop(1)
这是个先冻结原本的Activity,再交出直接存取屏幕能力(Pause状态)的过程。直 到Activity2完成一般启动流程后,Activity1才会被停止。
返回原Activity
- onPause(2) -> onRestart(1) -> onStart(1) -> onResume(1) -> onStop(2) -> onDestroy(2)
在新的Activity2中,点选硬件的Back按钮,回退到原本的Activity1。点Back按钮可以回到原本的Activity。
退出结束
- onPause -> onStop -> onDestroy
如果程序中有直接呼叫”finish”函式来关闭Activity的话,系统假设我们很确定我们 在做什么,因此会直接跳过先冻结(Freeze)的阶段,暂停(Pause),停止(Stop),然后销毁(Destroy)。
回收后再启动
- onCreate ->onStart ->onResume
被回收掉的Activity一旦又重新被呼叫时,会像一般启动一样再次呼叫Activity的onCreate函数。这个和前面第一个步骤中的一般启动是一样的流程。
当我们使用”Android”手机一阵子,在手机上已经执行过多个应用程序。只要按下”Back” (返回)键,”Android”就会开启最近一次开启过的Activity。
这时我们要是多次按“返回”键,理论上迟早会返回到某个已经销毁(Destroy)的Activity,这时会发生什么呢?
如果应该打开的Activity已经被回收了,那么这个Activity会再次被创建(Create)出来,再次被创建出来的Activity,当然会跟原本我们打开的Activity不一样。
所以如果要让再次被创建出来的Activity看起来跟原本打开的一样,那么在Activity之间切换时,我们就要留意数据的保存:最好在每次Activity运行到”onPause”或者”onStop”状态时先保存数据,然后在”onCreate”时将数据读出来。