现在的位置: 首页 > 综合 > 正文

Activity的生命周期

2018年05月12日 ⁄ 综合 ⁄ 共 6158字 ⁄ 字号 评论关闭

Activity的生命周期图


        一个Android应用程序通常由多个Activity组成,其中有一个“主Activity”是在应用启动时第一个显示的Activity。主Activity可以启动其它的Activity。新启动的Activity又可以再启动其他新的Activity。最新启动的Activity将覆盖之前的Activity,从而形成一个“Activity栈”。当启动新的Activity时上一个Activity会进入暂停状态。当用户按“BACK”按键时,“Activity栈”最上面的那个Activity出栈,之前的Activity又重新显示在屏幕上并恢复到运行状态。这意味着Activiy具有一个“生命周期”。

         Activitiy的生命周期图如下图所示:

QQ截图20120518103413.png
图1  Activity生命周期活动图

         从图中可以看到每一个Activity都处于一个特定状态,对于开发者来说,是无法设置Activity处于某一个状态,这些均由Android系统框架来完成。但是当一个活动的状态发生改变的时候,开发者可以通过覆盖Activity的onXxxxx() 的方法获取到对应的回调通知。当Activity的状态发生变化时会调用以下七个方法:

         onCreate :当Activity第一次启动的时调用,可以在这个方法中完成一些Acitivity的初始化工作。 onCreate方法有一个参数savedInstanceState,该参数可以为空(null),也可以是onSaveInstanceState()方法保存的状态信息。
         onStart :当Activity初始化结束,准备显示到屏幕时调用。
         onResume :当Activity显示到屏幕上能够与用户发生交互的时调用。
         onPause :当一个正在前台运行的Activity因为其他的acitivity需要前台运行,而转入后台运行的时调用。这时可以在onSaveInstanceState()方法中将活动的状态保存起来。
         onStop :当一个Activity不再需要显示时调用。如果内存紧张,系统会直接结束这个Activity而不会调用 onStop方法。所以保存状态信息是应该在onPause方法中处理,而不是onStop。onRestart :当处于停止状态的Activity需要再次显示时调用。
          onDestroy :当Activity被销毁时调用。与 onStop 方法一样,如果内存紧张,系统会直接结束这个Activity而不会调用onDestroy方法。

          除了这些方法以外Activity还提供了onSaveInstanceState() 和 onRestoreInstanceState()两个方法。它们并不一定会被调用,只有当应用遇到特殊情况(如:内存不足、用户直接按Home键)由系统销毁Activity时,onSaveInstanceState()才会被调用。当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

二、Activity的四种状态


1、活动状态
          Android系统通过Activity栈来管理Activity,这一点之后会讲到。当一个Activity在栈顶,它是可视的、有焦点、可接受用户输入数据。Android试图尽最大可能保持它活动状态,销毁其它Activity来确保当前活动Activity有足够的资源可以使用。当另外一个Activity被激活时,这个Activity将会进入暂停状态。 
2、暂停状态
         在一些情况下,Activity可视但是它没有焦点,换句话说它被暂停了。有可能是因为一个透明或者非全屏的Activity被激活。 当被暂停,一个Activity仍可能会当成活动状态,只不过是不可以接受用户输入。在极特殊的情况下,Android将会销毁一个暂停的Activity来为活动的Activity提供充足的资源。当一个Activity变为完全隐藏,它将会进入停止状态。
3、停止状态
         当一个Activity不是可视的,它是处于停止状态。这个Activity将仍然在内存中保存它所有的状态和资源信息。尽管如此,当其它地方需要内存时,它将是最有可能被销毁的。当一个Activity停止后,一个很重要的步骤是要保存数据和当前Acitivity状态。如果一个Activity退出或关闭了,它将进入待用状态。
4、待用状态
         当一个Activity被关闭或被装载前,它是处于待用状态的。待用状态的Acitivity被移除Activity栈,并且会在需要显示的时候重新启动它。

三、Activity的生命周期循环


1、完整的生命周期
          自第一次调用onCreate()开始,直至调用onDestroy()为止。Activity在onCreate()中设置所有全局状态以完成初始化,而在onDestroy()中释放所有系统资源。如果Activity有一个线程在后台运行从网络下载数据,它会在onCreate()中创建线程,而在onDestroy()中销毁线程。

2、可视生命周期
          自onStart()调用开始直到对应的onStop()调用结束。在此期间,用户可以在屏幕上看到Activity,也许它并不是位于前台或者也不与用户进行交互。在这两个方法之间,我们可以保留这个Activity需要的所有资源。当用户不再看见显示的内容时,可以在onStart()中注册一个BroadcastReceiver来监控会影响UI的变化,而在onStop()中来注消。onStart() 和 onStop() 方法可以随着应用程序是否为用户可见而被多次调用。

3、前台生命周期
          自onResume()调用起,至对应的onPause()调用为止。在此期间,Activity位于前台最上面并与用户进行交互。Activity会经常在暂停和恢复之间进行状态转换。当设备转入休眠状态或者有新的Activity启动时,将调用onPause() 方法。当Activity从子Activity获得结果或者接收到新的Intent时会调用onResume() 方法。

四、Activity中四个重要的概念

          为了更深入的理解Activity的生命周期,还需要了解以下四个重要的概念:Activity 栈、Task(任务)、 Affinity(公用性)、 Activity的加载模式。

1、Activity 栈
          每个Activity的状态是由它在Activity栈中的位置决定的,Activity栈是一个后进先出的数据结构,包含所有正在运行Activity。当一个新的Activity启动时,它将会移到Activity栈的顶部。如果用户使用后退按钮返回的话,或者前台的Activity结束时,之前的Activity将会移上来并进入活动状态。
每次启动新的Activity都将被添加到Activity 栈顶,用户可以方便的返回上一个Activity直到Home Screen。到达Home Screen后,将无法再继续查看堆栈记录。

          相对于Views、Windows、Menus和Dialogs而言,Activity是唯一可被记录在历史栈中的数据,如果你所设计的应用程序需要用户由A界面进入到次一级界面B,当完成操作后需要再次返回A,那么必须考虑将A看作为 Activity,否则将无法从历史堆栈中返回。

2、Task(任务)
          当需要一个Activity可以启动另一个Activity,可能另外一个Activity是定义在不同应用程序中的Activity。假设我们想在的应用中显示一些地图位置信息。而系统里已经有一个Activity可以做到这一点,因此,你的Activity所需要做的只是在Intent对象中添加必要的信息,并传递给startActivity()方法,地图浏览将会显示你的地图位置信息。当用户按下BACK键,你的Activity会再次出现在屏幕上。对于用户来说,看起来好像是地图浏览与你的Activity一样,属于相同的应用程序,即便是它定义在其它的应用程序里,并运行在那个应用程序的进程里。

        Android通过将这两个Activity保存在同一个Task里来体现这一用户体验。简单来说,一个Task就是用户体验上的一个“应用”。它将相关的Activity组合在一起,以Stack的方式管理就形成Task的概念。在Android平台上可以将Task简单的理解为有多个Activity共同协作完成某项功能,而不管Activity具体属于哪个应用程序。

3、Activity的加载模式
          在android的多activity开发中,activity之间的跳转可能需要有多种方式,有时是生成一个新activity实例,有时希望跳转到原来某个activity实例,而不是生成大量的重复的activity。加载模式可以决定以哪种方式启动一个实例,或者跳转到原来某个Activity实例。

          加载模式允许用户定义一个新的Activity实例和当前Task之间的关系。用户可以通过以下两种方式定义不同的加载模式:
          1)在配置manifest文件时,编辑<activity>元素下的android:launchMode属性。
          launchMode属性可以设置为一下不同的值:

          “standard”:默认的加载模式,系统在当前Task(启动这个Activity的Task)的栈顶创建一个新的Activity实例,并将Intent传递给这个新的实例。
        Activity可以被实例化许多次,每一个实例可以属于不同的Task。同时,一个Task也可以包含许多实例。

          “singleTop”:如果已经有一个Activity实例位于当前Task的Activity栈顶,就不创建新的Activity实例,只是通过调用Activity中的onNewInstance()方法将Intent传递给Activiy。否则,加载过程和“standard”相同。
        Activity可以被实例化许多次,每一个实例可以属于不同的Task。同时,一个Task也可以包含许多实例。

          “singleTask”:系统创建一个新的Task,并实例化Activity作为这个新的Task的栈底(root)。但是,如果其他的Task中已经包含了这个Activity的实例,系统就通过调用Activity的onNewInstance()的方法将Intent传递给Activity,而不再创建新的Activity实例。
        同一时间只能存在一个Activity的实例。

          “singleInstance”:和“singleTask”相同,不同点在于:Android系统不会再在包含该Activity的Task中加载任何其他的Activity。该Activity是包含它的Task中的唯一的成员,并且由它启动的任何其他Activity都将在新的Task中打开。也就是说,在这个模式下的Activity实例所处的task中只能有一个activity实例。

          2)使用Intent的不同flag,决定在调用startActivity()时,被加载Activity的加载模式。

          Intent中可以决定加载模式的flag有如下几个:

          FLAG_ACTIVITY_NEW_TASK:与launchMode属性中的“singleTask”相同。

          FLAG_ACTIVITY_SINGLE_TOP:与launchMode属性中的“singleInstance”相同。
          FLAG_ACTIVITY_CLEAR_TOP:如果该Activity的实例存在于当前Task中,那么所有在该Activity实例之上的其他Activity全部清空(destroy),然后系统通过调用onNewIntent()方法将Intent传递给该Activity的实例。否则,正常启动Activity。
          FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TOP经常配合使用。

          关于Activity的加载模式,内容比较复杂也比较多,本文所讲到的内容有限。读者如果希望进一步了解,可以参考Android文档中的内容,网址如下:

4、Activity 任务共用性
          在某些情况下,Android系统需要知道一个Activity属于哪个Task,即使它没有被启动到一个具体的Task里,这是通过任务共用性(Affinities)完成的。任务共用性(Affinities)为这个运行一个或多个Activity的Task提供了一个独特的静态名称,默认情况下,Activity的任务共用性(Affinity)是这个acitivity所在应用的包名。
          当启动一个没有Intent.FLAG_ACTIVITY_NEW_TASK标志的Activity时,它总是运行在启动它的Task里。如果使用了Intent.FLAG_ACTIVITY_NEW_TASK标志,那么共用性(affinity)将被用来判断是否已经存在一个具有相同共用性(affinity)的Task。如果存在,这个Task将被切换到栈顶,而新的Activity会启动于这个Task的顶层。
          这种特性在你必须使用Intent.FLAG_ACTIVITY_NEW_TASK标志的情况下最有用,尤其是从状态栏飞通知或桌面快捷方式启动Activity时。当用户用这种方式启动你的应用程序时,它的当前Task将被切换到前台,而且启动的Activity被放在最上面。 你可以在程序清单(Manifest)文件的应用程序application标签中为应用程序包中所有的Acitivity分配任务共用性Affinites,或者在每个activity标签中为Acitivity进行分配任务共用性Affinites。

          参考网址如下:
          http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html

抱歉!评论已关闭.