Android生命周期相关总结
目录
前言
当用户浏览、退出和返回到应用时,应用中的 Activity 实例会在其生命周期的不同状态间转换。Activity
Activity Activity
类提供许多回调让 Activity 知晓某个状态已经更改:系统正在创建、停止或恢复某个 Activity,或者正在销毁该 Activity 所在的进程。
在生命周期回调方法中,我们可以声明用户离开和再次进入 Activity 时 Activity 的行为方式。例如,如果正构建流媒体视频播放器,当用户切换至另一应用时,可能要暂停视频或终止网络连接。当用户返回时,可以重新连接网络并允许用户从同一位置继续播放视频。换言之,每个回调都支持执行适合给定状态变更的特定作业。在合适的时间执行正确的作业,并妥善处理转换,这将提升应用的稳健性和性能。
良好的生命周期回调实现有助于防止应用出现以下问题:
- 当用户在使用应用时接听来电,或切换至另一应用时崩溃。
- 当用户未主动使用它时,消耗宝贵的系统资源。
- 当用户离开应用并在稍后返回时,丢失用户的进度。
- 当屏幕在横向和纵向之间旋转时,崩溃或丢失用户的进度。
本文将介绍 Activity 生命周期。首先介绍生命周期范例。接着介绍每个回调:它们执行时内部发生了什么,以及应该在执行期间实现什么。然后,简要介绍 Activity 状态与导致进程被系统终止的漏洞之间的关系。最后,讨论与在 Activity 状态之间转换相关的若干主题。
一、Activity 生命周期概念
为了在 Activity 生命周期的各个阶段之间导航转换,Activity 类提供六个核心回调:onCreate()
、onStart()
、onResume()
、onPause()
、onStop()
和 onDestroy()
。当 Activity 进入新状态时,系统会调用其中每个回调。下图是对此范例的直观展现。
图 1. Activity 生命周期的简化图示。
三种经典的调用场景:
- 一个Activity启动另一个Activity: onPause()->onStop(),再返回:onRestart()->onStart()->onResume()
- 程序按back 退出: onPause()->onStop()->onDestory(),再进入:onCreate()->onStart()->onResume();
- 程序按home 退出: onPause()->onStop(),再进入:onRestart()->onStart()->onResume();
当用户开始退出 Activity 时,系统会调用方法来销毁该 Activity。在某些情况下,此销毁只是部分销毁;Activity 仍然驻留在内存中(例如当用户切换至另一应用时),并且仍然可以返回到前台。如果用户返回到该 Activity,Activity 会从用户离开时的位置继续运行。除了少数例外,应用在后台运行时会受到限制,无法启动 Activity。
系统终止给定进程及其中 Activity 的可能性取决于当时 Activity 的状态。
熟练掌握每个生命周期方法,并实现能够确保应用按用户预期方式运行的方法非常重要。
二、Activity三种状态
(1)active:当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于活动状态,同一个时刻只会有一个Activity处于活动(Active)。
(2)paused:当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出窗口时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但是当系统内存极小时可以被系统杀掉。
(3)stoped:完全被另一个Activity遮挡时处于停止状态,它仍然在内存中保留着所有的状态和成员信息。只是对用户不可见,当其他地方需要内存时它往往被系统杀掉。
三、Activity六个主要回调方法
本部分介绍 Activity 生命周期中所用回调方法的相关概念及实现信息。
1.onCreate()
程序中必须实现此回调,它会在系统首次创建 Activity 时触发。Activity 会在创建后进入“已创建”状态。在 onCreate()
方法中,需执行基本应用启动逻辑,该逻辑在 Activity 的整个生命周期中只应发生一次。例如,onCreate() 的实现可能会将数据绑定到列表,将 Activiy 与 ViewModel 相关联,并实例化某些类作用域变量。此方法会接收 savedInstanceState
参数,后者是包含 Activity 先前保存状态的 Bundle
对象。如果 Activity 此前未曾存在,Bundle
对象的值为 null。
onCreate()
方法的以下示例显示执行 Activity 某些基本设置的一些代码,例如声明界面(在 XML 布局文件中定义)、定义成员变量,以及配置某些界面。在本示例中,系统通过将文件的资源 ID R.layout.main_activity
传递给 MainActivity
来指定 XML 布局文件并在终端输出日志信息。
@Override //完全生命周期开始时被调用,初始化 Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "(1) onCreate()--205787");
}
除了定义 XML 文件,然后将其传递给 MainActivity
,还可以在 Activity 代码中新建 View
对象,并将新建的 View
插入到 ViewGroup
中,以构建视图层次结构。然后,将根 ViewGroup
传递给 MainActivity
以使用该布局。
Activity 并未处于“已创建”状态。onCreate()
方法完成执行后,Activity 进入“已开始”状态,系统会相继调用 onStart()
和 onResume()
方法。
2.onStart()
当 Activity 进入“已开始”状态时,系统会调用此回调。onStart()
调用使 Activity 对用户可见,因为应用会为 Activity 进入前台并支持互动做准备。例如,应用可通过此方法来初始化维护界面的代码。下面是利用onstart()获取view宽高并在输出日志信息。
@Override //可视生命周期开始时被调用,对用户界面进行必要的更改
public void onStart() {
super.onStart();
ViewTreeObserver observer = view.getViewTreeObserver();
observer.adddOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = view.gerMeasureWidth();
int height = view.getMeasureHeight();
}
});
Log.i(TAG, "(2) onStart()--205787");
}
当 Activity 进入已开始状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_START 事件。onStart()
方法会非常快速地完成,并且与“已创建”状态一样,Activity 不会一直处于“已开始”状态。一旦此回调结束,Activity 便会进入“已恢复”状态,系统将调用 onResume()
方法。
3.onResume()
Activity 会在进入“已恢复”状态时来到前台,然后系统调用 onResume()
回调。这是应用与用户互动的状态。应用会一直保持这种状态,直到某些事件发生,让焦点远离应用。此类事件包括接到来电、用户导航到另一个 Activity,或设备屏幕关闭。
@Override //在活动生命周期开始时被调用,恢复被onPause()停止 的用于界面更新的资源
public void onResume() {
super.onResume();
Log.i(TAG, "(4) onResume()--205787");
}
当 Activity 进入已恢复状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_RESUME 事件。这时,生命周期组件可以启用在组件可见且位于前台时需要运行的任何功能,例如启动相机预览。
当发生中断事件时,Activity 进入“已暂停”状态,系统调用 onPause()
回调。如果 Activity 从“已暂停”状态返回“已恢复”状态,系统再次调用 onResume()
方法。因此,应实现 onResume()
,以初始化在 onPause() 期间释放的组件,并执行每次 Activity 进入“已恢复”状态时必须完成的任何其他初始化操作。
无论选择在哪个构建事件中执行初始化操作,都要使用相应的生命周期事件来释放资源。在收到 ON_START 事件后初始化某些内容,要在收到 ON_STOP 事件后释放或终止相应内容。在收到 ON_RESUME 事件后初始化某些内容,要在收到 ON_PAUSE 事件后将其释放。
4.onPause()
系统将此方法视为用户将要离开 Activity 的第一个标志(尽管这并不总是意味着 Activity 会被销毁);此方法表示 Activity 不再位于前台(尽管在用户处于多窗口模式时 Activity 仍然可见)。使用 onPause() 方法暂停或调整当 Activity 处于“已暂停”状态时不应继续(或应有节制地继续)的操作,以及希望很快恢复的操作。Activity 进入此状态的原因有很多。例如:
- 如 onResume() 部分所述,某个事件会中断应用执行。
- 在 Android 7.0(API 级别 24)或更高版本中,有多个应用在多窗口模式下运行。无论何时,都只有一个应用(窗口)可以拥有焦点,因此系统会暂停所有其他应用。
- 有新的半透明 Activity(例如对话框)处于开启状态。只要 Activity 仍然部分可见但并未处于焦点之中,它便会一直暂停。
@Override //在活动生命周期结束时被调用,用来保存持久的数据或释放占用的资源
public void onPause() {
super.onPause();
Log.i(TAG, "(7) onPause()--205787");
}
当 Activity 进入已暂停状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_PAUSE 事件。这时,生命周期组件可以停止在组件未位于前台时无需运行的任何功能。
还可以使用 onPause() 方法释放系统资源,或当 Activity 暂停且用户不需要它们时仍然可能影响电池续航时间的任何资源。然而,正如上文的 onResume() 部分所述,如果处于多窗口模式,“已暂停”的 Activity 仍完全可见。因此,应该考虑使用 onStop() 而非 onPause() 来完全释放或调整与界面相关的资源和操作,以便更好地支持多窗口模式。
onPause()
执行非常简单,而且不一定要有足够的时间来执行保存操作。因此,不应使用 onPause()
来保存应用或用户数据、进行网络调用或执行数据库事务。因为在该方法完成之前,此类工作可能无法完成。相反,应在 onStop()
期间执行高负载的关闭操作。
onPause()
方法的完成并不意味着 Activity 离开“已暂停”状态。相反,Activity 会保持此状态,直到其恢复或变成对用户完全不可见。如果 Activity 恢复,系统将再次调用 onResume()
回调。如果 Activity 从“已暂停”状态返回“已恢复”状态,系统会让 Activity
实例继续驻留在内存中,并会在系统调用 onResume()
时重新调用该实例。如果 Activity 变为完全不可见,系统会调用 onStop()
。下一部分将介绍 onStop()
回调。
5.onStop()
如果 Activity 不再对用户可见,说明其已进入“已停止”状态,因此系统将调用 onStop()
回调。例如,当新启动的 Activity 覆盖整个屏幕时,可能会发生这种情况。如果 Activity 已结束运行并即将终止,系统还可以调用 onStop()
。
@Override //在可视生命周期结束时被调用,一般用来保存持久的数据或释放占用的资源
public void onStop() {
super.onStop();
Log.i(TAG, "(8) onStop()--205787");
}
当 Activity 进入已停止状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_STOP 事件。这时,生命周期组件可以停止在组件未显示在屏幕上时无需运行的任何功能。
在 onStop()
方法中,应用应释放或调整在应用对用户不可见时的无用资源。使用 onStop()
而非 onPause()
可确保与界面相关的工作继续进行,即使用户在多窗口模式下查看 Activity 也能如此。
当 Activity 进入“已停止”状态时,Activity
对象会继续驻留在内存中:该对象将维护所有状态和成员信息,但不会附加到窗口管理器。Activity 恢复后,Activity 会重新调用这些信息。无需重新初始化在任何回调方法导致 Activity 进入“已恢复”状态期间创建的组件。系统还会追踪布局中每个 View
对象的当前状态,如果用户在 EditText
微件中输入文本,系统将保留文本内容,因此无需保存和恢复文本。
注意:Activity 停止后,如果系统需要恢复内存,可能会销毁包含该 Activity 的进程。即使系统在 Activity 停止后销毁相应进程,系统仍会保留 Bundle
(键值对的 blob)中 View
对象(例如 EditText
微件中的文本)的状态,并在用户返回 Activity 时恢复这些对象。
进入“已停止”状态后,Activity 要么返回与用户互动,要么结束运行并消失。如果 Activity 返回,系统将调用 onRestart()
。如果 Activity
结束运行,系统将调用 onDestroy()
。
6.onDestroy()
销毁 Activity 之前,系统会先调用 onDestroy()。系统调用此回调的原因如下:
- Activity 即将结束(由于用户彻底关闭 Activity 或由于系统为 Activity 调用 finish())
- 由于配置变更(例如设备旋转或多窗口模式),系统暂时销毁 Activity
当 Activity 进入已销毁状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_DESTROY 事件。这时,生命周期组件可以在 Activity 被销毁之前清理所需的任何数据。
@Override //在完全生命周期结束时被调用,释放资源,包括线程、 数据连接等
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "(9) onDestroy()--205787");
}
如果 Activity 即将结束,onDestroy() 是 Activity 收到的最后一个生命周期回调。如果由于配置变更而调用 onDestroy(),系统会立即新建 Activity 实例,然后在新配置中为新实例调用 onCreate()。
onDestroy() 回调应释放先前的回调(例如 onStop())尚未释放的所有资源。
三、Activity 状态和从内存中弹出
系统会在需要释放 RAM 时终止进程;系统终止给定进程的可能性取决于当时进程的状态。反之,进程状态取决于在进程中运行的 Activity 的状态。表 1 展示了进程状态、Activity 状态以及系统终止进程的可能性之间的关系。
系统终止进程的可能性 | 进程状态 | Activity 状态 |
---|---|---|
较小 | 前台(拥有或即将获得焦点) | 已创建 已开始 已恢复 |
较大 | 后台(失去焦点) | 已暂停 |
最大 | 后台(不可见) | 已停止 |
空 | 已销毁 |
表 1. 进程生命周期和 Activity 状态之间的关系
系统永远不会直接终止 Activity 以释放内存,而是会终止 Activity 所在的进程。系统不仅会销毁 Activity,还会销毁在该进程中运行的所有其他内容。
四、生命周期详细总结
1.Android三个嵌套循环
- Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束。
- Activity的可视生命周期:从调用onStart()到相应的调用onStop()。在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop()中注销。
- Activity的前台生命周期:从调用onResume()到相应的调用onPause()。
2.BroadcastReceiver广播接收器生命周期
生命周期只有十秒左右,如果在onReceive()内做超过十秒内的事情,就会报ANR(Application No Response)程序无响应的错误信息。它的生命周期为从回调onReceive()方法开始到该方法返回结果后结束。
3.Service服务生命周期
Service完整的生命周期从调用onCreate()开始直到调用onDestroy()结束。
Service有两种使用方法:
- 以调用Context.startService()启动,而以调用Context.stopService()结束。
- 以调用Context.bindService()方法建立,以调用Context.unbindService()关闭。
4.一个activity的启动过程
- 第一个Activity的启动顺序:onCreate()——>onStart()——>onResume()
- 当另一个Activity启动时:第一个Activity onPause()——>第二个Activity onCreate()——>onStart()——>onResume()——>第一个Activity onStop()
- 当返回到第一个Activity时:第二个Activity onPause()——> 第一个Activity onRestart()——>onStart()——>onResume()——>第二个Activity onStop()——>onDestroy()
每一个Activity都处于某一个状态,对于开发者来说,是无法控制其应用程序处于某一个状态的,这些均由系统来完成。
总结
以上为在学习Android生命周期时对生命周期的一些个人知识总结