了解Activity生命周期
当用户浏览、退出和返回到您的应用时,您应用中的 [Activity](https://developer.android.google.cn/reference/android/app/Activity)
实例会在其生命周期的不同状态间转换。[Activity](https://developer.android.google.cn/reference/android/app/Activity)
类会提供许多回调,
这些回调会让 Activity 知晓某个状态已经更改:
系统正在创建、
停止或恢复某个 Activity,
或者正在销毁该 Activity 所在的进程。
在生命周期回调方法中,您可以声明用户离开和再次进入 Activity 时 Activity 的行为方式。
例如,如果您正构建流媒体视频播放器,当用户切换至另一应用时,您可能要暂停视频或终止网络连接。
当用户返回时,您可以重新连接网络并允许用户从同一位置继续播放视频。
换言之,每个回调都支持您执行适合给定状态变更的特定作业。
在合适的时间执行正确的作业,并妥善处理转换,这将提升应用的稳健性和性能。例如,良好的生命周期回调实现有助于防止应用出现以下问题:
- 当用户在使用应用时接听来电,或切换至另一应用时崩溃。
- 当用户未主动使用它时,消耗宝贵的系统资源。
- 当用户离开应用并在稍后返回时,丢失用户的进度。
- 当屏幕在横向和纵向之间旋转时,崩溃或丢失用户的进度。
为了在 Activity 生命周期的各个阶段之间导航转换,Activity 类提供六个核心回调:[onCreate()](https://developer.android.google.cn/reference/android/app/Activity#onCreate(android.os.Bundle))
、[onStart()](https://developer.android.google.cn/reference/android/app/Activity#onStart())
、[onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
、[onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
、[onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
和 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity#onDestroy())
。当 Activity 进入新状态时,系统会调用其中每个回调。
onCreate()
您必须实现此回调,它会在系统首次创建 Activity 时触发。
Activity 会在创建后进入“已创建”状态。
在 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity#onCreate(android.os.Bundle))
方法中,您需执行基本应用启动逻辑,该逻辑在 Activity 的整个生命周期中只应发生一次。例如,onCreate()
) 的实现可能会将数据绑定到列表,将 Activity 与 ViewModel
相关联,并实例化某些类作用域变量。此方法会接收 savedInstanceState
参数,后者是包含 Activity 先前保存状态的 [Bundle](https://developer.android.google.cn/reference/android/os/Bundle)
对象。如果 Activity 此前未曾存在,[Bundle](https://developer.android.google.cn/reference/android/os/Bundle)
对象的值为 null。
如果您有一个生命周期感知型组件与您的 Activity 生命周期相关联,该组件将收到 ON_CREATE
事件。系统将调用带有 @OnLifecycleEvent 注释的方法,以使您的生命周期感知型组件可以执行已创建状态所需的任何设置代码。[onCreate()](https://developer.android.google.cn/reference/android/app/Activity#onCreate(android.os.Bundle))
方法的以下示例显示执行 Activity 某些基本设置的一些代码,例如声明界面(在 XML 布局文件中定义)、定义成员变量,以及配置某些界面。在本示例中,系统通过将文件的资源 ID R.layout.main_activity
传递给 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity#setContentView(android.view.View))
来指定 XML 布局文件。
lateinit var textView: TextView
// some transient state for the activity instance
var gameState: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
//调用父类onCreate来完成像视图层次结构一样的活动的创建
super.onCreate(savedInstanceState)
// recovering the instance state
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
// set the user interface layout for this activity
// the layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity)
// initialize member TextView so we can manipulate it later
textView = findViewById(R.id.text_view)
}
// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}
// invoked when the activity may be temporarily destroyed, save the instance state here
override fun onSaveInstanceState(outState: Bundle?) {
outState?.run {
putString(GAME_STATE_KEY, gameState)
putString(TEXT_VIEW_KEY, textView.text.toString())
}
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState)
}
除了定义 XML 文件,然后将其传递给 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity#setContentView(android.view.View))
,您还可以在 Activity 代码中新建 [View](https://developer.android.google.cn/reference/android/view/View)
对象,并将新建的 [View](https://developer.android.google.cn/reference/android/view/View)
插入到 [ViewGroup](https://developer.android.google.cn/reference/android/view/ViewGroup)
中,以构建视图层次结构。然后,将根 [ViewGroup](https://developer.android.google.cn/reference/android/view/ViewGroup)
传递给 [setContentView()](https://developer.android.google.cn/reference/android/app/Activity#setContentView(android.view.View))
以使用该布局。如需详细了解如何创建界面,请参阅界面文档。
您的 Activity 并未处于“已创建”状态。[onCreate()](https://developer.android.google.cn/reference/android/app/Activity#onCreate(android.os.Bundle))
方法完成执行后,Activity 进入“已开始”状态,系统会相继调用 [onStart()](https://developer.android.google.cn/reference/android/app/Activity#onStart())
和 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
方法。下一部分将介绍 [onStart()](https://developer.android.google.cn/reference/android/app/Activity#onStart())
回调。
onStart()
当 Activity 进入“已开始”状态时,系统会调用此回调。[onStart()](https://developer.android.google.cn/reference/android/app/Activity#onStart())
调用使 Activity 对用户可见,因为应用会为 Activity 进入前台并支持互动做准备。例如,应用通过此方法来初始化维护界面的代码。
当 Activity 进入已开始状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_START
事件。
[onStart()](https://developer.android.google.cn/reference/android/app/Activity#onStart())
方法会非常快速地完成,并且与“已创建”状态一样,Activity 不会一直处于“已开始”状态。一旦此回调结束,Activity 便会进入“已恢复”状态,系统将调用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
方法。
onResume()
Activity 会在进入“已恢复”状态时来到前台,然后系统调用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
回调。这是应用与用户互动的状态。应用会一直保持这种状态,直到某些事件发生,让焦点远离应用。此类事件包括接到来电、用户导航到另一个 Activity,或设备屏幕关闭。
当 Activity 进入已恢复状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_RESUME
事件。这时,生命周期组件可以启用在组件可见且位于前台时需要运行的任何功能,例如启动相机预览。
当发生中断事件时,Activity 进入“已暂停”状态,系统调用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
回调。
如果 Activity 从“已暂停”状态返回“已恢复”状态,系统将再次调用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
方法。因此,您应实现 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
,以初始化在 onPause()
) 期间释放的组件,并执行每次 Activity 进入“已恢复”状态时必须完成的任何其他初始化操作。
以下是生命周期感知型组件的示例,该组件在收到 ON_RESUME
事件时访问相机:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}
onPause()
系统将此方法视为用户将要离开您的 Activity 的第一个标志(尽管这并不总是意味着 Activity 会被销毁);此方法表示 Activity 不再位于前台(尽管在用户处于多窗口模式时 Activity 仍然可见)。使用 onPause()
) 方法暂停或调整当 Activity
处于“已暂停”状态时不应继续(或应有节制地继续)的操作,以及您希望很快恢复的操作。Activity 进入此状态的原因有很多。例如:
- 如 onResume() 部分所述,某个事件会中断应用执行。这是最常见的情况。
- 在 Android 7.0(API 级别 24)或更高版本中,有多个应用在多窗口模式下运行。无论何时,都只有一个应用(窗口)可以拥有焦点,因此系统会暂停所有其他应用。
- 有新的半透明 Activity(例如对话框)处于开启状态。只要 Activity 仍然部分可见但并未处于焦点之中,它便会一直暂停
当 Activity 进入已暂停状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_PAUSE
事件。这时,生命周期组件可以停止在组件未位于前台时无需运行的任何功能,例如停止相机预览。
您还可以使用 onPause()
) 方法释放系统资源、传感器(例如 GPS)手柄,或当您的 Activity 暂停且用户不需要它们时仍然可能影响电池续航时间的任何资源。然而,正如上文的 onResume() 部分所述,如果处于多窗口模式,“已暂停”的 Activity 仍完全可见。因此,您应该考虑使用 onStop() 而非 onPause() 来完全释放或调整与界面相关的资源和操作,以便更好地支持多窗口模式。
响应 ON_PAUSE 事件的以下 LifecycleObserver
示例与上述 ON_RESUME 事件示例相对应,会释放在收到 ON_RESUME 事件后初始化的相机:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun releaseCamera() {
camera?.release()
camera = null
}
...
}
请注意,上述代码段在 LifecycleObserver 收到 ON_PAUSE 事件后放置相机释放代码。如前所述,请参阅使用生命周期感知型组件处理生命周期了解如何创建生命周期感知型组件。
[onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
执行非常简单,而且不一定要有足够的时间来执行保存操作。因此,您不应使用 [onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
来保存应用或用户数据、进行网络调用或执行数据库事务。因为在该方法完成之前,此类工作可能无法完成。相反,您应在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
期间执行高负载的关闭操作。如需详细了解在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
期间执行的合适操作,请参阅 onStop()。如需详细了解如何保存数据,请参阅保存和恢复 Activity 状态。
[onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
方法的完成并不意味着 Activity 离开“已暂停”状态。相反,Activity 会保持此状态,直到其恢复或变成对用户完全不可见。如果 Activity 恢复,系统将再次调用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
回调。如果 Activity 从“已暂停”状态返回“已恢复”状态,系统会让 [Activity](https://developer.android.google.cn/reference/android/app/Activity)
实例继续驻留在内存中,并会在系统调用 [onResume()](https://developer.android.google.cn/reference/android/app/Activity#onResume())
时重新调用该实例。在这种情况下,您无需重新初始化在任何回调方法导致 Activity 进入“已恢复”状态期间创建的组件。如果 Activity 变为完全不可见,系统会调用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
。下一部分将介绍 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
回调。
onStop()
如果您的 Activity 不再对用户可见,说明其已进入“已停止”状态,因此系统将调用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
回调。例如,当新启动的 Activity 覆盖整个屏幕时,可能会发生这种情况。如果 Activity 已结束运行并即将终止,系统还可以调用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
。
当 Activity 进入已停止状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_STOP
事件。这时,生命周期组件可以停止在组件未显示在屏幕上时无需运行的任何功能。
在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
方法中,应用应释放或调整在应用对用户不可见时的无用资源。例如,应用可以暂停动画效果,或从精确位置更新切换到粗略位置更新。使用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
而非 [onPause()](https://developer.android.google.cn/reference/android/app/Activity#onPause())
可确保与界面相关的工作继续进行,即使用户在多窗口模式下查看您的 Activity 也能如此。
您还应使用 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
执行 CPU 相对密集的关闭操作。例如,如果您无法找到更合适的时机来将信息保存到数据库,可以在 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
期间执行此操作。以下示例展示了 [onStop()](https://developer.android.google.cn/reference/android/app/Activity#onStop())
的实现,它将草稿笔记内容保存到持久性存储空间中:
override fun onStop() {
// call the superclass method first
super.onStop()
// save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
val values = ContentValues().apply {
put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText())
put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle())
}
// do this update in background on an AsyncQueryHandler or equivalent
asyncQueryHandler.startUpdate(
token, // int token to correlate calls
null, // cookie, not used here
uri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
)
}
请注意,上述代码示例直接使用 SQLite。但您应该改用 Room,这是一个通过 SQLite 提供抽象层的持久性库。如需详细了解使用 Room 的好处,以及如何在应用中实现 Room,请参阅 Room 持久性库指南。
当您的 Activity 进入“已停止”状态时,[Activity](https://developer.android.google.cn/reference/android/app/Activity)
对象会继续驻留在内存中:该对象将维护所有状态和成员信息,但不会附加到窗口管理器。Activity 恢复后,Activity 会重新调用这些信息。您无需重新初始化在任何回调方法导致 Activity 进入“已恢复”状态期间创建的组件。系统还会追踪布局中每个 [View](https://developer.android.google.cn/reference/android/view/View)
对象的当前状态,如果用户在 [EditText](https://developer.android.google.cn/reference/android/widget/EditText)
微件中输入文本,系统将保留文本内容,因此您无需保存和恢复文本。
注意:Activity 停止后,如果系统需要恢复内存,可能会销毁包含该 Activity 的进程。即使系统在 Activity 停止后销毁相应进程,系统仍会保留
[Bundle](https://developer.android.google.cn/reference/android/os/Bundle)
(键值对的 blob)中[View](https://developer.android.google.cn/reference/android/view/View)
对象(例如[EditText](https://developer.android.google.cn/reference/android/widget/EditText)
微件中的文本)的状态,并在用户返回 Activity 时恢复这些对象。如需详细了解如何恢复用户返回的 Activity,请参阅保存和恢复 Activity 状态。
**
进入“已停止”状态后,Activity 要么返回与用户互动,要么结束运行并消失。如果 Activity 返回,系统将调用 [onRestart()](https://developer.android.google.cn/reference/android/app/Activity#onRestart())
。如果 [Activity](https://developer.android.google.cn/reference/android/app/Activity)
结束运行,系统将调用 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity#onDestroy())
。下一部分将介绍 [onDestroy()](https://developer.android.google.cn/reference/android/app/Activity#onDestroy())
回调。
onDestroy()
销毁 Ativity 之前,系统会先调用 onDestroy()
)。系统调用此回调的原因如下:
- Activity 即将结束(由于用户彻底关闭 Activity 或由于系统为 Activity 调用
finish()
)),或者 - 由于配置变更(例如设备旋转或多窗口模式),系统暂时销毁 Activity
当 Activity 进入已销毁状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_DESTROY
事件。这时,生命周期组件可以在 Activity 被销毁之前清理所需的任何数据。
您应使用 ViewModel
对象来包含 Activity 的相关视图数据,而不是在您的 Activity 中加入逻辑来确定 Activity 被销毁的原因。如果因配置变更而重新创建 Activity,ViewModel 不必执行任何操作,因为系统将保留 ViewModel 并将其提供给下一个 Activity 实例。如果不重新创建 Activity,ViewModel 将调用 onCleared()
) 方法,以便在 Activity 被销毁前清除所需的任何数据。
您可以使用 isFinishing()
) 方法区分这两种情况。
如果 Activity 即将结束,onDestroy() 是 Activity 收到的最后一个生命周期回调。如果由于配置变更而调用 onDestroy(),系统会立即新建 Activity 实例,然后在新配置中为新实例调用 onCreate()
)。
onDestroy()
) 回调应释放先前的回调(例如 onStop()
))尚未释放的所有资源。