前言
这篇记录笔者在复习Activity生命周期及其拓展
一、常见生命周期
一般地,我们认为我们日常开发需要使用和了解的生命周期大致有如下六类
- onCreate()
- onStart()
- onResume()
- onPause()
- onStop()
- onDestory()
我们一般通过是否可交互/可见/可存在来区分以上的生命周期
更详细的,结合一些常用的场景和方法,我们一般认为Activity的生命周期和其他方法有如下关系
二、生命周期具体分析
1.onCreate()
当Activity创建实例完成,并调用attach方法赋值PhoneWindow、ContextImpl等属性之后,调用此方法。该方法在整个Activity生命周期内只会调用一次。调用该方法后Activity进入ON_CREATE状态。
该方法是我们使用最频繁的一个回调方法。
我们需要在这个方法中初始化基础组件和视图。如viewmodel,textview。同时必须在该方法中调用setContentView来给activity设置布局。
这个方法接收一个参数,该参数保留之前状态的数据。如果是第一次启动,则该参数为空。该参数来自onSaveInstanceState存储的数据。只有当activity暂时销毁并且预期一定会被重新创建的时候才会被回调,如屏幕旋转、后台应用被销毁等
2.onStart()
onStart:当Activity准备进入前台时会调用此方法。调用后Activity会进入ON_START状态。
一般的,我们认为onStart()方法表示Activity进入了可见状态,但更为核心的理解是此时Activity出于返回栈的顶端这个方法一般用于从一个Activity切换回一个Activity或新Activity启动
3.onResume()
onResume:当Activity准备与用户交互的时候调用。调用之后Activity进入ON_RESUME状态。
此时的活动一定位于返回栈的栈顶,并且处于运行状态。
4.onPause()
onPause:当前activity窗口失去焦点的时候,会调用此方法。调用后activity进入ON_PAUSE状态,并进入后台。
我们通常会在这个方法中将一些及其消耗 CPU 的资源释放掉(比如显示地图或者大规模图形),以及保存一些关键数据(比如用户输入的数据等等),但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
5.onStop()
onStop:当activity不可见的时候进行调用。调用后activity进入ON_STOP状态。
当activity不可交互时会回调onPause方法并进入ON_PAUSE状态。但如果进入的是另一个全屏的activity而不是小窗口,那么当新的activity界面显示出来的时候,原Activity才会进入ON_STOP状态,并回调onStop方法。同时,activity第一创建的时候,界面是在onResume方法之后才显示出来,所以onStop方法会在新activity的onResume方法回调之后再被回调。
注意,被启动的activity并不会等待onStop执行完毕之后再显示。因而如果onStop方法里做一些比较耗时的操作也不会导致被启动的activity启动延迟。
onStop方法的目的就是做资源释放操作。因为是在另一个activity显示之后再被回调,所以这里可以做一些相对重量级的资源释放操作,如中断网络请求、断开数据库连接、释放相机资源等。
如果一个应用的全部activity都处于ON_STOP状态,那么这个应用是很有可能被系统杀死的。而如果一个ON_STOP状态的activity被系统回收的话,系统会保留该activity中view的相关信息到bundle中,下一次恢复的时候,可以在onCreate或者onRestoreInstanceState中进行恢复。
6.onRestart()
这个方法一般在activity从ON_STOP状态被重新启动的时候会调用。执行该方法后会立即执行onStart方法,然后Activity进入ON_START状态,进入前台。
7.onDestory()
onDestroy:当activity被系统杀死或者调用finish方法之后,会回调该方法。调用该方法之后activity进入ON_DESTROY状态。
三、引起生命周期的回调方法
onActivityResult
结合startActivityForResult一起使用。
具体地结合上面那张图这么分析
onSaveInstanceState/onRestoreInstanceState
这两个方法,主要用于在Activity被意外杀死的情况下进行界面数据存储与恢复。什么叫意外杀死呢?
如果你主动点击返回键、调用finish方法、从多任务列表清除后台应用等等,这些操作表示用户想要完整得退出activity,那么就没有必要保留界面数据了,所以也不会调用这两个方法。而当应用被系统意外杀死,或者系统配置更改导致的activity销毁,这个时候当用户返回activity时,期望界面的数据还在,则会通过回调onSaveInstanceState方法来保存界面数据,而在activity重新创建并运行的时候调用onRestoreInstanceState方法来恢复数据。事实上,onRestoreInstanceState方法的参数和onCreate方法的参数是一致的,只是他们两个方法回调的时机不同。因此,判断是否执行的关键因素就是用户是否期望返回该activity时界面数据仍然存在。
onNewIntent
这个方法涉及到的场景也是重复启动,但是与onRestart方法被调用的场景是不同的。
我们知道activity是有多种启动模式的,其中singleInstance、singleTop、singleTask都保证了在一定情况下的单例状态。如singleTop,如果我们启动一个正处于栈顶且启动模式为singleTop的activity,那么他并不会在创建一个activity实例,而是会回调该activity的onNewIntent方法。该方法接收一个intent参数,该参数就是新的启动Intent实例。
四、场景生命周期流程
正常启动
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy
Activity切换
Activity1:onPause Activity2:onCreate -> onStart -> onResume
Activity1:onStop
屏幕旋转
running -> onPause -> onStop -> onSaveInstanceState -> onDestroy
onCreate -> onStart -> onRestoreInstanceState -> onResume
当因资源配置改变时,activity会销毁重建,最常见的就是屏幕旋转。这个时候属于异常情况的Activity生命结束。因而,在销毁的时候,会调用onSaveInstanceState来保存数据,在重新创建新的activity的时候,会调用onRestoreInstanceState来恢复数据。
后台应用被系统杀死
onDestroy
onCreate -> onStart -> onRestoreInstanceState -> onResume
这个流程跟上面的资源配置更改是很像的,只是每个activity不可见的时候,会回调onSaveInstanceState提前保存数据,那么在被后台杀死的时候,就不需要再次保存数据了。
具有返回值的启动
onActivityResult -> onRestart -> onResume
这里主要针对使用startActivityForResult方法启动另一个activity,当该activity销毁并返回时,原activity的onActivityResult方法的执行时机。大部分流程和activity切换是一样的。但在返回原Activity时,onActivityResult方法会在其他所有的生命周期方法执行前被执行
五、常见的面试题提问
1、假设项目中有这样的需求,当指定的 Activity 在用户可见后才进行广播的注册,在用户不可见后对广播进行注销,那应该在哪两个回调中做这个处理呢?
注意可见和不可见,所以抓住onStart()和onStop()
2.如果有一些数据在 Activity 跳转时(或者离开时)要保存到数据库,那么你认为是在 onPause() 好还是在 onStop() 执行这个操作好呢?
要结合看数据重要性、数据操作耗时性
onPause()的优势在于更易于执行,毕竟可能Activity还没执行到onStop()就被回收
onStop()的优势在于存储的耗时操作不会影响下一个Activity
3.Activity A 启动了 Activity B,简单说下它们分别的生命周期的变化。
4.Activity A 通过 Intent 显示启动了 Activity B,当 B 处于可见状态后,A 是否一定会调用 onStop()?
这两题的常规思路上面的分析已经给出,但是要注意ActivityA不一定调用onStop()方法
比如Activity B是dialog形式的Activity,或者Activity B的不透明度被降低
总结
暂时就整理到这里,后续继续完善