Activity 生命周期和启动模式

Activity 角色浅析

在 Android 应用中,Activity 作为四大组件之一,扮演着举足轻重的角色。首先作为与用户的直接交互者,Activity 可以展示多种多样的内容,其次作为业务逻辑的主要处理单元,Activity 里包含着许多业务逻辑,在 Activity 中,通过 Intent 等途径和其他的 Activity 和组件进行信息交流,需要和展示较多的数据单元,和数据层有着较强的耦合性,不过在这里,会有例如 MVP、MVVM 等优秀的设计模式来优化界面和数据耦合性的问题,后续探讨,暂不细述。

Activity 是一个应用组件,可以充满屏幕也可以浮动于其他窗口之上,一般来讲,它是一个应用重要的组成部分,在开发中会指定一个“主要”的 Activity 作为程序的入口,而 Activity 在程序中则是存在于任务栈中,类似于栈的数据结构操作,Android 中提供了四种 Activity 的启动模式,分别为:standard (标准模式)、singleTop(栈顶复用)、singleTask(栈内复用)、singleInstance(单实例模式)。

Activity 继承自 android.view.ContextThemeWrapper, 所以在开发中会发现 Activity 是一个层级视图的对象,每个视图控制着 Activity 窗口内特定的矩形区域,并且可以对用户的交互做出相应。Activity 的层级视图可以由 XML 文件和 Java 共同控制,在 Activity 的生命周期中,调用 setContentView() 加载布局,也可以在 Activity 中通过 Java 代码创建新的 View,并通过将新的 View 插入到 ViewGroup 中来创建视图的层次,通过跟 ViewGroup 传递到 setContentView() 来使用该布局。

Activity 是一个可以玩出很多花样的组件,无论是炫酷和简约的 Android APP,只要你需要界面,那么 Activity 将是必须用到的东西,但是无论花样再多,其内在的核心是不变的,所以来探究一下其生命周期和启动模式。

Activity 生命周期

任务和返回栈

应用中通常会有许多 Activity,最初的开发中,没有在程序中执行 finish() 方法来销毁 Activity,当多次点击启动新的 Activity 时,会导致启动的窗口堆积,查阅文档,发现 Android 所采用的活动管理方案是通过 Task(任务),一个任务就是一组存放在栈里的集合,这个栈也被称作返回栈(Back Stack)。在数据结构中,栈是一种先进后出结构,所以在默认的情况下,启动一个新的 Activity,它会在返回栈入栈,并处在栈顶的位置,当按下 Back 键时, 系统会执行 finish() 方法,从而栈顶元素出栈,前一个入栈的 Activity 就会出现在栈顶,系统会将栈顶的 Activity 展示在前台。
backstack

Activity 存在状态

每一个 Activity 在应用中的存在状态分为四种类型:运行、暂停、停止、销毁。四种状态可以和 Activity 的生命周期相对应起来。

  • Activity 处于运行状态时,位于返回栈栈顶,系统一般不会回收正在运行的 Activity。
  • Activity 处于暂停状态时,其不再位于返回栈栈顶,但仍然处于可见状态,例如虽然不是当前 Activity,但是以对话框的形式存在。处于暂停状态下的 Activity 系统极少回去回收,除非在内存极低的情况下,否则不会回收处于暂停状态下的 Activity。
  • Activity 处于停止状态时,其不再处于返回栈栈顶,并且完全不可见,此时便处于停止状态。停止状态下系统仍然会保留相应的状态和成员变量,但是并不可靠,在某一些地方需要更多的内存时,停止状态下的 Activity 会被回收。
  • Activity 处于销毁状态时,从返回栈移除,这种状态下的 Activity 被系统回收的优先级最高。

Activity 的生存期

Activity 中有七个回调方法,分别指向 Activity 生命周期的不同环节,同时也对应着不同的生存期,主要分为:完整生存期、可见生存期、前台生存期三种。
在 Android 的开发文档 中,可以找到如下的生命周期图示:

activity_ligecycle

从文档和图示中可以清晰的看到这七个回调方法:

  • onCreate() 生命周期的第一个方法,执行 Activity 的创建、初始化操作
  • onStart() 启动 Activity,在 Activity 由不可见变为可见的时候调用
  • onResume() 在 Activity 做好和用户交互的情况下调用,表示已经可见,并且出现在了前台
  • onPause() Activity 正在停止,通常在系统准备启动或恢复另外一个 Activity 的时候启动,在该方法中经常会将一些消耗 CPU 的资源释放掉,或者保存一些关键的数据,不过该方法不能处理耗时操作,否则会影响新的 Activity 启动。
  • onStop() 一般在 onPause() 方法启动之后,用于在 Activity 完全不可见的时候调用,可以处理一些重的回收操作,但是同样不能太耗时。
  • onDestory() 在被销毁之前调用,在此可以做一些回收和最终的资源释放。
  • onReStart() 在 Activity 由停止状态到运行状态之前调用,重新启动 Activity。

Activity 的七个回调方法,除了 onRestart() 方法之外,均是两两相对,据此将生命周期分为三个阶段,分别为:

  • 完整生存期
    在 onCreate() 和 onDestroy() 方法之间所经历的,为完整的生存期。
    囊括整个 Activity 的创建到销毁的过程。
  • 可见生存期
    从 onStart() 到 onStop() 之间的生存阶段,在可见生存期内, Activity 处于可见状态,即便有可能无法与用户交互,通过这两个方法,合理的处理用户可见的资源,比如在 onStart() 方法中加载资源,在 onStop() 中释放,从而使在停止阶段的 Activity 不至于占用过多的内存。
  • 前台生存期
    在 onResume() 和 onPause() 方法之间,活动处于运行状态,并且可以和用户交互,这种状态的 Activity 日常中接触的最多,

关于 Activity 生命周期的问题,很多都可以通过查看源码解决,比如在 Activity A 中打开一个新的窗口 B,那么 B 中的 onResume 和 A 中的 onPause 哪个最先执行的,在查阅源码中的 ActivityStack.java 文件中的 resumeTopActivityInnerLocked 方法后可以看出:在新的 Activity 启动之前,栈顶的 Activity 需要先 onPause 后,新的 Activity 才会启动……

等等。

另外,在异常情况下的时候,Activity 的生命周期会有所不同,但是在 Activity 中均有对应的方法来保存数据和状态,从而具体情况要具体分析,通过解决一个又一个的问题才能对整个的生命周期掌握的熟练和细致。

Activity 启动模式

standard

默认启动模式,每次打开 Activity 均会创建一个 Activity 实例放到栈中,无论这个实例是否存在,均会创建。
生命周期中的 onCreate、onStart、onResume 方法均会正常调用。

singleTop

栈顶复用模式,在这种模式下,若新的 Activity 位于栈顶,那么 Activity 将不会被重新创建,同时回调它的 onNewIntent 方法,通过方法参数取出当前的请求信息,同时 onCreate、onStart 方法将不会调用,若新的 Activity 不位于栈顶,则新的 Activity 仍然会重建。

singleTask

栈内复用模式。这是一种单实例模式,在这种模式下,只要 Activity 在一个栈中存在,那么多次启动此 Activity 均不会创建新的实例,类似上述的 singleTop,系统会调用 onNewIntent 方法。在该模式下的 Activity,系统会首先寻找是否存在该 Activity 想要的返回栈,如果没有则创建将其放入,如果存在则看该 Activity 是否存在于,不存在则创建,存在则调用 onNewIntent 方法。

singleInstance

单实例模式。有人称之为加强风的 singleTask 模式,除了具有 singleTask 的所有特性外,加强了一个点,就是具有此模式的 Activity 只能单独的存在于一个任务栈中,当其启动时候,系统会创建一个新的任务栈,然后独立的运行在这里,由于栈内复用的特性,后续的不会创建新的 Activity,直到该任务栈被销毁。

关于启动模式,开发中没有用到的实例,所以不敢多纸上谈兵,仅此。

参考资料

Android API 文档
《Android 开发艺术探索》
《第一行代码》

坚持原创技术分享,您的支持将鼓励我继续创作!
0%