Android之Activity生命周期讲解

2015/02/01 14:04
阅读数 86

Activity生命周期

维护一个 Activity 的生命周期非常重要,因为 Activity 随时会被系统回收掉。

生命周期:

现在使用者使用智慧型手机,大多已习惯使用多工 (Multi-Task) 的操作系统 ( 如 Window sMobile),可以在用手机听音乐的同时,也执行其他多个程序。同时执行多个程序有它的明显好处,但是也有它的严重的缺点。每多执行一个应用程序,就会多耗费一些系统记忆体 。而手机里的记忆体是相当有限的。当同时执行的程序过多,或是关闭的程序没有正确释放掉记忆体,执行系统时就会觉得越来越慢,甚至不 稳定。为了解决这个问题, Android 引入了一个新的机制 -- 生命周期 (LifeCycle) 。

行程:

应用程序(一个个Activity )执行的状态称为行程(process) 。在 Android 操作系统 中 ,每个应用程序都是一个行程。 Android 系统平台 ( 准确的说是 Dalvik 虚拟机 ) 会维护一个唯一的 Activity 历史记录堆叠,并从旁观察每个应用程序行程。系统平台会依照系统的记 忆体状况,与 Activity 的使用状态,来管理记忆体的使用。Activity 类别除了负责运行程序流程,与操作界面元件之外,最重要的,就是它提供 了开发者控制行程生命周期的函式。我们已经相当习惯在 OnCreate (建立行程时的行为 ) 函数中,加入我们对这个 Activity 执行流程的控制。在前面遇到的范例中,我们并不需要对 除了 OnCreate 之外的行为做出改变。不过理解行程的生命周期,将为我们继续深入 Androi d开发打下基础。

为什麽要了解生命周期?

Android 应用程序的生命周期是由 Android 框架进行管理,而不是由应用程序直接控

制。通常,每一个应用程序(入口一般会是一个 Activity 的 onCreate 方法),都会占据一个行程 (Process) 。当系统记忆体即将不足的时候,会依照优先级自动进行行程 (process )的回收。不管是使用者或开发者,都无法确定的应用程序何时会被回收。一个 Activity 类别除了 OnCreate 函数之外,还预先定义了 OnPause( 暂停行程时的 行为 ) 、 OnResume( 继续行程时的行为 ) 等等的基本行为,当从一个 Activity 切换到另一个Activity 的时候,原本的 Activity 将经过一连串的状态改变。开发者可以在程序中添加一些各状态相对应的流程,每次 Activity 改变状态时,就会执行相对应的流程。

Activity 的状态

Android 的虚拟机 (VM) 是使用堆叠 (Stackbased) 管理。主要有四种状态:

* Active ( 活动 )

* Paused ( 暂停 )

* Stopped ( 停止 )

* Dead ( 已回收或未启动 )
Active ( 活动 )

"Active" 状态是使用者启动应用程序或 Activity 后, Activity 运行中的状态。在 Android 平台上,同一个时刻只会有一个 Activity 处于活动 (Active) 或运行(Running) 状态。其他的 Activity 都处于未启动 (Dead) 、停止 (Stopped) 、或是暂停 (Paus e)的状态。

Paused ( 暂停 )

"Paused" 状态是当 Activity 暂时暗下来,退到背景画面的状态。当我们使用 Toast 、 AlertDialog 、或是电话来了时,都会让原本运行的 Activity 退到背景画面。新出现的 Toast 、 AlertDialog 等界面元件盖住了原来的 Activity 画面。Activity 处在 "Paused" 状态时,使用者无法与原 Activity 互动。

Stopped ( 停止 )

Stopped" 状态是有其他 Activity 正在执行,而这个 Activity 已经离开萤幕,不再动作的状态。透过长按 "Home"钮,可以叫出所有处于 "Stopped"状态的应用程序列表。在"Stopped" 状态的 Activity ,还可以透过 "Notification" 来唤醒。 "Notification"会在后面章节中解说。

Dead ( 已回收或未启动 )

"Dead" 状态是 Activity 尚未被启动、已经被手动终止,或已经被系统回收的状态。要手动终止Activity ,可以在程序中呼叫"finish" 函数。如果是被系统回收,可能是因为记忆体不足了,所以系统根据记忆体不足时的回收规则,将处于 "Stopped" 状态的 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();
}
}
}


讲解

我们为 Activity 的各个状态加入了 "Log" 记录讯息。当模拟器运行时,我们可以透过"LogCat"工具来查看 Activity所处在的状态。

上面的七个状态又可以归纳成三组:

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" 状态,此时又直接存取萤幕。

Activity 运作流程

由实际运行的记录来看,我们可以归纳出所有 Android 应用程序都遵循的动作流程:一般启动onCreate -> onStart -> onResume

启动一个 Activity 的基本流程是:分配资源给这个 Activity ( Create 状态),然 后将 Activity 内容显示到萤幕上( Start 状态)。在一切就绪后,取得萤幕的控制权( Res ume状态),使用者可以开始使用这个程序。

呼叫另一个 Activity

onPause(1) -> onCreate(2) ->onStart(2) - onResume(2) -> onStop(1)

这是个先冻结原本的Activity ,再交出直接存取萤幕能力(Pause 状态)的过程。 直到 Activity 2 完成一般启动流程后, Activity 1 才会被停止。

还原 Activity

onPause(2) -> onRestart(1) ->onStart(1) -> onResume(1) -> onStop(2) ->onDestroy(2)

点 Back 按钮可以回到原本的 Activity 。

退出结束

onPause -> onStop -> onDestroy

如果程序中有直接呼叫"finish" 函数来关闭 Activity 的话,系统假设我们很确定我们在做什麽,因此会直接跳过先冻结 (Freeze) 的阶段,暂停 (Pause) ,停止 (Stop) ,然后销毁(Destroy) 。

回收后再启动

onCreate ->onStart ->onResume

被回收掉的 Activity一旦又重新被呼叫时,会像一般启动一样再次呼叫 Activity 的onCreate 函数。

当我们使用"Android" 手机一阵子,在手机上已经执行过多个应用程序。只要按下 "Back"(返回)键, "Android" 就会开启最近一次开启过的 Activity 。这时我们要是按下多次 "Back" (返回)键,理论上迟早会返回到某个已经销毁( Destroy )的 Activity 。这时会发生什麽事呢?

如果应该开启的Activity 已经被回收了,那么这个Activity 会再次被建立( Create )出来。再次被建立出来的Activity ,当然会跟原本我们开启过的Activity 不一样啦。所以如果要让再次被建立出来的 Activity 看起来跟原本开启过的一样,那么在Activity 之间切换时,我们就要留意保留资料:最好在每次 Activity 运行到 "onPause"或 "onStop" 状态时先保存资料,然后在 "onCreate" 时将资料读出来。

参考资料


onSaveInstanceState和onRestoreInstanceState触发的时机

先看Application Fundamentals上的一段话: 
Android callsonSaveInstanceState() before the activity becomes vulnerable to being destroyedby the system, but does not bother calling it when the instance is actuallybeing destroyed by a user action (such as pressing the BACK key) 
从这句话可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。 

通过重写一个activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况: 
1、当用户按下HOME键时。 
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则 
2、长按HOME键,选择运行其他的程序时。 
3、按下电源按键(关闭屏幕显示)时。 
4、从activity A中启动一个新的activity时。 
5、屏幕方向切换时,例如从竖屏切换到横屏时。 

在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行 

总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。 

至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activityA“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行 

另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原 

 





展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部