再看艺术开发探索之Activity的生命周期和启动模式

Activity 作为四大组件之一,也是平常接触最多的,以前对于 Activity 的使用其实也有点人云亦云,只知道要在 onCreate() 里去做一些初始化工作,不要在 onResume() 或是 onPause() 中做一些耗时操作,总之就是,别人怎么做,我也怎么做,没有想过为什么要这么做,在通读了 Android 开发艺术探索第一章之后,对于 Activity 的了解深入了一点,也解答了自己内心的很多困惑,特此个记录~

生命周期

Activity 的生命周期如下图所示(图片来源于 Android Developers):

Activity 生命周期

  • onCreate() Activity 正在被创建,主要用于做一些初始化工作,如加载布局资源等
  • onStart() Activity 正在被启动,此时 Activity 已可见,只是未出现在前台
  • onResume() Activity 显示在前台,处于可见状态
  • onPause() Activity 正在停止,可以做一些不太耗时的回收工作,因为会影响到新 Activity 的显示
  • onStop() Activity 即将停止
  • onDestory() Activity 即将被销毁,生命周期的最后一个回调方法
  • onRestart() Activity 正在重新启动,当 Activity 由不可见状态重新变为可见状态时调用,如进入新的界面后按 Back 返回

特殊情况

  • 点击 Home 键退出至桌面:onPause() –> onStop()
  • 点击 Back 键退出:onPause() –> onStop() –> onDestory()
  • 当打开新的 Activity 采用了透明主题时,当前 Activity 不会调用 onStop()
    onSaveInstanceState() 调用时机为 onStop() 之前,但和 onPause() 没有既定的时序关系
  • onRestoreInstanceState() 调用时机在 onStart() 之后
  • onRestoreInstanceState() 被调用时,其 Bundle 参数一定有值,onCreate() 的 Bundle 参数如果正常启动为 null

启动模式

Standard

标准模式,当没有 Activity 配置启动模式时,默认为这个,多次启动同一 Activity 会创建多个实例,如果 B 为标准模式,A 启动 B,则 B 会加入到 A 所在的栈中。使用 ApplicationContext 启动标准模式的 Activity 会报错,因为非 Activity 类型的 Context 没有任务栈。

示例

A 启动 B,当前 A 的栈内为 AB,则启动完成后,栈内为 ABB

SingleTop

栈顶复用模式,如果被启动 Activity 已处于栈顶,则不会被重新创建,同时 onNewIntent() 会被调用,可以获取到 Intent,onCreate()onStart() 不会调用,onResume() 会被调用。

示例

启动 B,当前栈内为 ABCD ,则启动完成后为 ABCDB, 如果时 AB,则启动完成后还是 AB,回调 onNewIntent()

SingleTask

栈内复用模式,只要存在于栈中,则不会被重新创建,且也会回调 onNewIntent() ,默认具有 clearTop 效果,会导致所有位于要启动 Activity 上面的 Activity 都出栈。

示例

  • S1 栈中为 ABC,此时启动 属于任务栈 S2 的 D,如果 S2 不存在,则会创建任务栈 S2,然后将 D 加入 S2
  • S2 栈中为 ABCD,此时启动 属于任务栈 S2 的 B,则 B 不会重新创建,会将 CD 出栈,只剩下 AB

任务栈

任务栈分为前台任务栈和后台任务栈,后台任务栈中的 Activity 处于暂停状态,用户可以通过切换将后台任务栈再次调到前台,当后台任务栈中的 Activity 被启动时,整个后台任务栈都会被切换到前台。
可以通过命令 adb shell dumpsys activity 来查看当前的所有 Activity 信息,通过搜索 Running 关键字来查询当前运行的 Activity 以及它的任务栈。
默认情况下所有 Activity 的任务栈的名字都是应用的包名,可以通过指定 TaskAffinity 属性来指定任务栈,任务栈在 SingleTask 模式下非常重要,例如在一个 Launcher 应用中,Launcher Activity有独立任务栈,A、B 启动模式都为SingleTask 且未指定任务栈,先启动 A,然后点 Home 键,接着启动 B,此时点击 Back 键,会发现回到了 A,这就是因为都没有指定任务栈,所以加入到了默认的栈中,因此在使用这种模式时,特定情况下,需要去指定任务栈。

SingleInstance

单实例模式,具有该模式的 Activity 单独处于一个任务栈中,可以理解为不需要手动设置任务栈的 singleTask 模式。

设置

指定启动模式有两种方式,一种是在 Manifest 文件中注册 Activity 时添加 launchMode 属性,还有就是在启动 Activity 时,给 Intent 设置标志位,例如设置 singleTask 则可以给 Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 标识位。

注意

  • 当两种方式都存在时,以第二种方式为准;
  • 第一种方式无法添加 FLAG_ACTIVITY_CLEAR_TOP 标识;
  • 第二种方式无法指定 SingleInstance 模式。

参考

Androdi Developer: Activity