Activity 状态变化

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

如需详细了解 Activity 状态,请参阅Activity 生命周期。如需了解 ViewModel 类如何帮助您管理 Activity 生命周期,请参阅 ViewModel 概览

发生配置变更

有许多事件会触发配置变更。最突出的例子可能是纵向和横向方向之间的切换。其他可能导致配置变更的情况包括语言设置或输入设备的变更。

当发生配置变更时,Activity 会被销毁并重新创建。这会在原始 Activity 实例中触发以下回调:

  1. onPause()
  2. onStop()
  3. onDestroy()

系统会创建 Activity 的新实例,并触发以下回调:

  1. onCreate()
  2. onStart()
  3. onResume()

结合使用 ViewModel 实例、onSaveInstanceState() 方法或持久性本地存储来跨配置变更保留 Activity 的界面状态。如何结合使用这些选项取决于您的界面数据的复杂性、应用的使用场景以及对检索速度与内存使用情况的考量。如需详细了解如何保存 Activity 界面状态,请参阅保存界面状态

处理多窗口情况

当应用进入多窗口模式(Android 7.0 (API 级别 24) 及更高版本提供)时,系统会通知正在运行的 Activity 发生了配置变更,从而经历前面所述的生命周期转换。

如果已处于多窗口模式的应用大小发生变化,也会出现此行为。您的 Activity 可以自行处理配置变更,也可以允许系统销毁 Activity 并以新尺寸重新创建它。

如需详细了解多窗口生命周期,请参阅多窗口支持页面中的多窗口生命周期说明。

在多窗口模式下,虽然有两个应用对用户可见,但只有用户正在交互的应用处于前台并获得焦点。该 Activity 处于 Resumed 状态,而另一个窗口中的应用则处于 Paused 状态。

当用户从应用 A 切换到应用 B 时,系统会调用应用 A 上的 onPause() 和应用 B 上的 onResume()。每当用户在应用之间切换时,系统都会在这两个方法之间切换。

如需详细了解多窗口模式,请参阅多窗口支持

Activity 或对话框显示在前台

如果新的 Activity 或对话框显示在前台,获得焦点并部分覆盖正在进行的 Activity,则被覆盖的 Activity 会失去焦点并进入 Paused 状态。然后,系统会对其调用 onPause()

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

如果新的 Activity 或对话框显示在前台,获得焦点并完全覆盖正在进行的 Activity,则被覆盖的 Activity 会失去焦点并进入 Stopped 状态。然后,系统会快速连续地调用 onPause()onStop()

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

用户点按或手势返回

如果 Activity 处于前台且用户点按或手势返回,则 Activity 会经历 onPause()onStop()onDestroy() 回调。该 Activity 会被销毁并从返回堆栈中移除。

默认情况下,onSaveInstanceState() 回调不会在这种情况下触发。此行为假定用户点按“返回”时没有返回同一 Activity 实例的预期。

但是,您可以替换 onBackPressed() 方法来实现自定义行为,例如显示对话框,要求用户确认他们是否要退出您的应用。

如果您替换了 onBackPressed() 方法,我们强烈建议您仍然从替换的方法中调用 super.onBackPressed()。否则,系统的返回行为可能会让用户感到不适。

系统终止应用进程

如果应用处于后台,并且系统需要为前台应用释放内存,则系统可能会终止后台应用。当系统终止应用时,无法保证应用中的 onDestroy() 会被调用。

如需详细了解系统如何决定销毁哪些进程,请阅读Activity 状态和内存逐出以及进程和应用生命周期

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