处理 Activity 状态更改

用户触发和系统触发的不同事件会导致 Activity 从一个状态转换到另一个状态。本文档介绍了发生此类转换的一些常见情况,以及如何处理这些转换。

有关 Activity 状态的详情,请参阅了解 Activity 生命周期。要了解如何借助 ViewModel 类来管理 Activity 生命周期,请参阅 了解 ViewModel 类

配置发生了更改

有很多事件会触发配置更改。最显著的例子或许是横屏和竖屏之间的屏幕方向变化。其他情况,如语言或输入设备的改变等,也可能导致配置更改。

当配置发生更改时,Activity 会被销毁并重新创建。原始 Activity 实例将触发 onPause()onStop()onDestroy() 回调。系统将创建新的 Activity 实例,并触发 onCreate()onStart()onResume() 回调。

结合使用 ViewModels、onSaveInstanceState() 方法和/或持久性本地存储,可使 Activity 的界面状态在配置发生更改后保持不变。在决定这些选项的组合方式时,需要考虑界面数据的复杂程度、应用的用例以及检索速度与内存使用的权衡。有关保存 Activity 界面状态的详情,请参阅保存界面状态

处理多窗口模式的情况

一旦应用进入多窗口模式(适用于 Android 7.0(API 级别 24)及更高级别),系统会向当前运行的 Activity 发送配置更改通知,从而完成上述生命周期转换。如果已经处于多窗口模式的应用调整了大小,也会出现这种行为。您的 Activity 可以自行处理配置更改,也可以让系统销毁 Activity 并使用新维度重新创建一个。

有关多窗口模式生命周期的详情,请参阅多窗口模式支持页的多窗口模式生命周期部分。

在多窗口模式下,虽然用户可以看到两个应用,但只有与用户交互的应用位于前台且具有焦点。该 Activity 处于“已恢复”状态,而另一个窗口中的应用则处于“已暂停”状态。

当用户从应用 A 切换到应用 B 时,系统会对应用 A 调用 onPause(),对应用 B 调用 onResume()。每当用户在应用之间切换时,系统就会在这两种方法之间切换。

有关多窗口模式的详情,请参阅多窗口模式支持

Activity 或对话框显示在前台

如果有新的 Activity 或对话框出现在前台,并且局部覆盖了正在进行的 Activity,则被覆盖的 Activity 会失去焦点并进入“已暂停”状态。然后,系统会调用 onPause()

当被覆盖的 Activity 返回到前台并重新获得焦点时,会调用 onResume()

如果有新的 Activity 或对话框出现在前台,夺取了焦点且完全覆盖了正在进行的 Activity,则被覆盖的 Activity 会失去焦点并进入“已停止”状态。然后,系统会快速地接连调用 onPause()onStop()

当被覆盖的 Activity 的同一实例返回到前台时,系统会对该 Activity 调用 onRestart()onStart()onResume()。如果被覆盖的 Activity 的新实例进入后台,则系统不会调用 onRestart(),而只会调用 onStart()onResume()

注意:当用户点按“概览”或主屏幕按钮时,系统的行为就好像当前 Activity 已被完全覆盖一样。

用户点按“返回”按钮

如果 Activity 位于前台,并且用户点按了返回按钮,Activity 将依次经历 onPause()onStop()onDestroy() 回调。活动不仅会被销毁,还会从返回堆栈中移除。

需要注意的是,在这种情况下,默认不会触发 onSaveInstanceState() 回调。此行为基于的假设是,用户点按返回按钮时不期望返回 Activity 的同一实例。不过,您可以通过替换 onBackPressed() 方法实现某种自定义行为,例如“confirm-quit”对话框。

如果您替换 onBackPressed() 方法,我们仍然强烈建议您从被替换的方法调用 super.onBackPressed()。否则,返回按钮的行为可能会让用户感觉突兀。

系统终止应用进程

如果某个应用处于后台并且系统需要为前台应用释放额外的内存,则系统可能会终止后台应用以释放更多内存。要详细了解系统如何确定要销毁哪些进程,请阅读 Activity 状态和从内存中弹出以及进程和应用生命周期

要了解如何在系统终止您的应用进程时保存 Activity 界面状态,请参阅保存和恢复 Activity 状态