6.2 Activity的生命周期

在Android中,一般用系统管理来决定进程的生命周期。有时因为手机所具有的一些特殊性,所以需要更多地去关注各个Android程序部分的运行时生命周期模型。所谓手机的特殊性,主要是指如下两点。

(1)在使用手机应用时,大多数情况下只能在手机上看到一个程序的一个界面,用户除了通过程序界面上的功能按钮来在不同的窗体间切换,还可以通过Back(返回)键和Home(主)键来返回上一个窗口,而用户使用Back或者Home的时机是非常不确定的,任何时候用户都可以使用Home或Back来强行切换当前的界面。

(2)通常手机上一些特殊的事件发生也会强制地改变当前用户所处的操作状态,例如无论任何情况,在手机来电时,系统都会优先显示电话接听界面。

了解了手机应用的上述特殊性之后,接下来将详细介绍Activity在不同阶段的生命周期。

6.2.1 Activity的几种状态

要想了解Activity在不同阶段的生命周期,首先需要了解Activity的几种状态。当Activity被创建或销毁时,会存在如下4种状态。

(1)Active(活动)。

当Activity在栈的顶端时是可见的,这些有焦点的前台Activity用来响应用户的输入。Android会不惜一切代价来尝试保证它的活跃性,需要的话它会杀死栈中更靠下的Activity,这样可以保证Active Activity需要的资源。当另一个Activity变成Active状态时,这个就会变成Paused。

(2)Paused(暂停)。

在一些情况下,程序Activity可见但是不拥有焦点,这时它就是暂停的。当最前面的Activity是全透明或非全屏的Activity时,下面的Activity就会到达这个状态。当暂停时,这个Activity还是被看作是Active的,但不接受用户的输入事件。在极端的情况下,Android会“杀死”一个Paused的Activity来恢复资源给Active Activity。当一个Activity完全不可见时,它就变成Stopped。

(3)Stopped(停止)。

当一个Activity不可见,它就“停止”了。这个Activity仍然留在内存里来保存所有的状态和成员信息;但是,在什么地方当系统需要内存时,它就是“罪犯”拉出去“枪毙”了。当一个Activity停止时,保存数据和当前UI状态是很重要的。一旦Activity退出或关闭,它就变成Inactive。

(4)Inactive(销毁)。

当一个曾经被启动过的Activity被“杀死”时,它就变成Inactive。Inactive Activity会从Activity栈中移除,当它重新显示和使用时需要再次启动。

Activity状态转换图如图6-1所示。

图6-1 Activity状态转换图

图6-1所示的状态的变化是由Android内存管理器决定的,Android会首先关闭那些包含Inactive Activity的应用程序,然后关闭Stopped状态的程序。在极端情况下,会移除Paused状态下的程序。

6.2.2 分解剖析Activity

(1)void onCreate(Bundle savedInstanceState)。

当Activity被第一次加载时执行onCreate(),当启动一个新程序的时候,其主窗体的onCreate事件就会被执行。如果Activity被onDestroy(销毁)后,再重新加载Task(任务)时,其onCreate()的事件也会被重新执行。

(2)void onStart()。

在onCreate事件之后执行onStart()。或者当前窗体被交换到后台后,在用户重新查看窗体前已经过去了一段时间,窗体已经执行了onStop()事件,但是窗体和其所在进程并没有被销毁,用户再次重新查看窗体时会执行onRestart()事件,之后会跳过onCreate()事件,直接执行窗体的onStart事件。

(3)void onResume()。

在onStart事件之后执行。或者当前窗体被交换到后台后,在用户重新查看窗体时,窗体还没有被销毁,也没有执行过onStop()事件(窗体还继续存在于Task中),则会跳过窗体的onCreate()和onStart()事件,直接执行onResume()事件。

(4)void onPause()。

窗体被交换到后台时执行onPause()。

(5)void onStop()。

onPause()事件之后执行onStop()。如果一段时间内用户还没有重新查看该窗体,则该窗体的onStop()事件将会被执行;或者用户直接按了Back键,将该窗体从当前Task中移除,也会执行该窗体的onStop()事件。

(6)void onRestart()。

onStop事件执行后执行onRestart(),如果窗体和其所在的进程没有被系统销毁,此时用户又重新查看该窗体,则会执行窗体的onRestart事件,onRestart事件后会跳过窗体的onCreate()事件直接执行onStart()事件。

(7)void onDestroy()。

Activity被销毁的时候执行onDestroy()。在窗体的onStop()事件之后,如果没有再次查看该窗体,Activity则会被销毁。

6.2.3 几个典型的场景

根据前面讲解的Activity生命周期的基本知识,可以总结出如下几个典型的应用场景。

(1)Activity从被装载到运行,执行顺序为:

        onCreate() -> onStart()-> onResume();

这是一个典型的过程,发生在Activity被系统装载运行时。

(2)Activity从运行到暂停,再到继续回到运行。执行顺序为:

        onPause() -> onResume();

这个过程发生在Activity被别的Activity遮住了部分UI,失去了用户焦点,另外那个Activity退出之后,这个Activity再次重新获得运行。在这个过程中,该Activity的实例是一直存在。

(3)Activity从运行到停止,执行顺序为:

        onPause() -> onStop();

这个过程发生在Activity的UI完全被别的Activity遮住了,当然也失去了用户焦点。这个过程中Activity的实例仍然存在。比如,当Activity正在运行时,按HOME键,该Activity就会被执行这个过程。

(4)Activity从停止到运行,执行顺序为:

        onRestart()-> onStart()-> onResume();

处于STOPPED状态并且实例仍然存在的Activity,再次被系统运行时,执行这个过程。这个过程是(3)的逆过程,只是要先执行onRestart()而重新获得执行。

(5)Activity从运行到销毁,执行顺序为:

        onPause() -> onStop() -> onDestroy();

这个过程发生在Activity完全停掉并被销毁了,所以该Activity的实例也就不存在了。比如,当Activity正在运行时,按BACK键,该Activity就会被执行这个过程。这个过程可看作是(1)的逆过程。

(6)被清除出内存的Activity重新运行,执行顺序为:

        onCreate() -> onStart()-> onResume();

这个过程对用户是透明的,用户并不会知道这个过程的发生,看起来如同(1)的执行顺序,不同的是如果保存有系统被清除存内存时的信息,会在调用onCreate()时,系统以参数的形式给出,而(1)中onCreate()的参数为null。

6.2.4 管理Activity的生命周期

此处说的管理Activity的生命周期,更确切地说应该是参与生命周期的管理,因为Android系统框架已经很好地管理了这其中的绝大部分,应用开发者要做的就是在Android的框架下,在Activity状态转换的各个时间点上,做出自己的实现,而实现这些要做的只是在你的Activity子类中Override这些Activity的方法即可。

图6-2列出了Activity生命周期相关的方法。

图6-2 Activity生命周期相关的方法

6.2.5 Activity的实例化与启动

Activity的实例化工作是由Android系统完成的,当用户点击执行一个Activity时,或另一个Activity需要执行这个Activity的时候,如果该Activity的实例不存在,Android系统都会将其实例化,并在该Activity所在进程的主线程中调用该Activity的onCreate()方法,实现Activity实例化时的工作。

由此可见,当Activity::onCreate()是系统实例化的Activity时,Activity可以被当作自身初始化的时机。在这里可以实例化变量,并可以调用Activity::setContentView()设置UI显示的内容。

一般来说,在Activity实例化之后就要启动该Activity,这样会在该Activity所在进程的主线程中顺序调用Activity的onStart()、onResume()。在Activity的生命周期的典型时序中,一般onStart()在所有的时序中都不是很特别的过程,所以一般不怎么实现。

图6-3演示了Activity实例化与启动的时序。

图6-3 Activity实例化与启动的时序

在Activity存续期内,只会调用onCreate()一次。如果另外又启动了一个Activity的实例,并通过onCreate()的参数传递进先前杀掉的Activtiy里保留的信息。因为onStart()可因为已经停止了,再次执行而被调用多次。onResume()可以因为Activity的PAUSED/RESUMED的不停转换,而被频繁调用。

6.2.6 Activity的暂停与继续

Activity因为被别的Activity遮住部分UI界面,并因此失去了焦点而被中段暂停,这种情况通常发生在系统进入睡眠时或被一个对话框打断时。在被暂停之前,系统会通过onPause()让Activity保留被暂停前状态的时机。Activity可以在onPause()中保存所做的修改到永久存储区,以停止动画显示等常见的操作。因为在onPause()返回之前不会调入其他的Activity运行,所以在onPause()中的操作必须简短并快速返回。此时Activity因为还会显示部分UI,并与Window Manager的链接依旧存在,所以一般不需保留对UI的修改。即便是在极端的情况下,当PAUSED的Activity所在的进程被“杀死”时,也不可能使Activity的UI显示完整一致。

系统在被唤醒或者打断它的对话框消失之后,会继续运行,此时系统会调用Activity的onResume()方法。在onResume()方法中可以做与onPause()中相对应的事情。

在图6-4中,演示了一个Activity启动同一个进程内另外一个Activity的时序图。

图6-4 一个Activity启动另一个Activity的时序图

图6-4可以很好地说明一个Activity启动时,与另外一个Activity之间的各种PAUSE/RESUME交互过程。在此需要注意,PAUSE/RESUME是众多Activity状态转换中的一个子集,很多其他的场景也需要经过这个过程。

6.2.7 Activity的关闭/销毁与重新运行

当Activity被Stop时,可能是完全被别的Activity覆盖掉了,也可能是用户显式地按了BACK或HOME键。Activity被Stop之前,它的onStop()方法会被提前调用,来做一些Stop前的处理。如果再次运行处于STOPPED的Activity,它的onRestart()方法会被调用,这是区分其他调用场景比较合适的实现处理的地方。

因为处于Paused状态的Activity在内存极端不足的情况下,它所在的进程也可能被“杀掉”,这样onStop()在被“杀掉”前,不一定会被调用,所以onPause()是比onStop()更合适的保留信息到永久存储区的时机。

Activity被销毁可能是显式地按了BACK键,也可能是处于Paused或Stopped状态,因为内存不足而被“杀掉”的。还有种情况是配置信息改变(比如屏的方向改变)之后,根据设置需要杀掉所有的Activity(是否关闭还要看Activity自己的配置),再重新运行它们。

被系统隐式“杀死”的Activity,在被“杀死”(onStop()调用)之前,一般的会调用onSaveInstanceState()保留该Activity此时的状态信息。该方法中传入Bundle参数,可在此方法中把此时的状态信息写入,系统保留这些信息。而当该Activty再次被实例化运行时,系统会把保留在Bundler的信息再次以参数形式,通过onCreate()方法传入。

通常在onSaveInstanceState()中保留UI的信息,永久存储的信息最好还是在onPause()中保存。Activity的onSaveInstanceState()已经缺省实现来保留通用View的UI信息,所以不管是否保留当前Activity的信息,通常都要在onSaveInstanceState()中先调用super.onSaveInstanceState()来保留通用的UI信息。

6.2.8 Activity的启动模式

在Android系统中,有以下4种启动Activity的模式。

standard(默认)。

singleTop。

singleTask。

singleInstance。

上述4种模式分别在文件AndroidManifest.xml中配置,另外也可以在intent启动Activity时添加必要参数来设置。例如下面的配置代码:

        <activity
        android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLa
        yout|fontScale|uiMode|orientation"
                <span style="color:#e53333; ">android:launchMode="singleTask"</span> android:screenOrientation="portrait"
                  android:windowSoftInputMode="adjustPan"
                android:name=".activity.ShowHowAct" >

接下来开始一一说明这4种模式的基本特征。

(1)standard(默认)。

standard是Android的Activity的默认模式,如果没有配置android:launchMode,则默认是这个模式。在该模式下,一个Activity可以同时被添加到多个task中,并且一个task可以有多个实例,且每次通过intent启动时,都会生成一个新的实例。

(2)singleTop。

属性singleTop和standard较类似,不同的地方就是,当当前Activity的实例在当前task的栈顶时,intent启动时,则不生成新的实例,会重用(不生成新的实例)原有的实例,如果显式指定intent的参数FLAG_ACTIVITY_NEW_TASK,如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。

(3)singleTask。

在singleTask模式下,Activity只会有一个实例。如果某一个task中已有该Activity的一个实例存在,则不再启动新的,每次都会被重用(重用就是如果该Activity在task的栈底,则会被调到栈顶),且可以和其他的Activity共存于一个task中。

(4)singleInstance。

singleInstance模式和singleTask模式一样,唯一的区别就是,在该模式下的Activity会独自拥有一个task,不会和其他Activity公用,每次Activity都会被重用,且全局只能有一个实例。