不同的事件(有些由用户触发,有些由系统触发)可能会导致 Activity
从一个状态转换为另一个状态。本文档介绍了发生此类转换的一些常见情况以及如何处理这些转换。
如需详细了解 Activity 状态,请参阅Activity 生命周期。如需了解 ViewModel
类如何帮助您管理 Activity 生命周期,请参阅 ViewModel 概览。
发生配置变更
有许多事件会触发配置变更。最突出的例子可能是纵向和横向方向之间的切换。其他可能导致配置变更的情况包括语言设置或输入设备的变更。
当发生配置变更时,Activity 会被销毁并重新创建。这会在原始 Activity 实例中触发以下回调:
系统会创建 Activity 的新实例,并触发以下回调:
结合使用 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 界面状态,请参阅保存和恢复瞬态界面状态。