Activity Lifecycle & LaunchMode

Activity_A 打开 Activity_B 时会有哪些生命周期回调

当 Activity_B 的 launchMode 为 Standard 或者 Activity_B 没有可复用的实例时:

A.onPause -> B.onCreate -> B.onStart -> B.onResume
                                     -> A.onStop -> A.onSaveInstanceState

当 Activity_B 的 launchMode 为 SingleTop 且 Activity_B 已经在栈顶时(如点击通知栏、连点):

B.onPause -> B.onNewIntent -> B.onResume

当 Activity_B 的 launchMode 为 SingleInstance 或 SingleTask 且 Activity_B 有可复用的实例时:

A.onPause -> B.onRestart -> B.onStart -> B.onNewIntent -> B.onResume
                                      -> A.onStop -> A.onSaveInstanceState

Dialog 对生命周期的影响

生命周期回调都是 AMS 通过 Binder 通知应用进程调用的,而 Dialog、Toast、PopupWindow 本质上都直接是通过 WindowManager.addView 来显示的(没有经过 AMS),所以不会对生命周期有任何影响

如果是启动一个 Theme 为 Dialog的Activity , 则生命周期为:A.onPause -> B.onCreate -> B.onStart -> B.onResume,注意这边没有前一个 Activity 不会回调 onStop,因为只有在 Activity 切到后台不可见才会回调 onStop

onActivityResult 回调时机

B.onPause -> A.onActivityResult -> A.onRestart -> A.onStart -> A.onResume

onCreate 方法里写死循环会触发 ANR 吗

ANR 的四种场景

  1. Service TimeOut:  Service未在规定时间执行完成
    1. 普通服务-前台进程 20s,普通服务-后台进程 200s
    2. 前台服务 10s
  2. BroadCastQueue TimeOut: 有序广播未在规定时间内未处理完成
    1. 前台广播 10s
    2. 后台广播 60s
  3. ContentProvider TimeOut
    1. publish 在 10s 内没有完成
    2. getResolver 20s 未获取成功(返回空,不会触发ANR)
  4. Input Dispatching timeout
    1. 5s 内未响应键盘输入、触摸屏幕等事件

我们可以看到,Activity 的生命周期回调的阻塞并不在触发 ANR 的场景里面,所以并不会直接触发 ANR。只不过死循环阻塞了主线程,如果系统再有上述的四种事件发生,就无法在相应的时间内处理从而触发 ANR

onRestart调用场景:

  • 按下home键之后,然后切换回来,会调用onRestart()
  • 从本Activity跳转到另一个Activity之后,按back键返回原来Activity,会调用onRestart()
  • 从本Activity切换到其他的应用,然后再从其他应用切换回来,会调用onRestart()

Activity任务栈

Task是一个具有栈结构的对象,一个Task可以管理多个Activity。Activity一共有四种launchMode:Standard、SingleTop、SingleTask、SingleInstance,我们可以在AndroidManifest.xml中通过Android:launchMode属性来配置Activity启动模式

1.Standard

Standard是默认的启动模式,不用为Activity配置android:launchMode属性即可,当然也可以指定为Standard,每次跳转系统都会在Task中生成一个新的Activity实例,并且放于栈结构的顶部

2.SingleTop

我们在上面的基础上为Activity指定属性android:launchMode="SingleTop",系统就会按照SingleTop启动模式处理跳转行为,系统发现Activity实例位于栈顶,则重复利用,调用onNewIntent方法,否则重新生成一个实例

3.SingleTask

当一个应用程序加载一个SingleTask模式的Activity时,首先会检查是否存在与它的taskAffinity相同的Task如果存在,那么检查是否实例化,如果已经实例化,那么销毁在该Activity以上的ActivityIntent.FLAG_ACTIVITY_CLEAR_TOP销毁目标Activity和它之上的所有Activity,重新创建目标Activity并调用onNewIntent如果没有实例化,那么该Activity实例化并入栈如果不存在,那么就重新创建Task并入栈

4.SingleInstance

SingleInstance模式会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入

当一个应用程序加载一个SingleInstance模式的Activity时,如果该Activity没有被实例化,那么就重新创建一个Task,并入栈,如果已经被实例化,那么就调用该Activity的onNewIntent,singleInstance的Activity所在的Task不允许存在其他Activity,任何从该Activity加载的其它Activity(假设为Activity2)都会被放入其它的Task中,如果存在与Activity2相同affinity的Task,则在该Task内创建Activity2,如果不存在,则重新生成新的Task并入栈

每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task,如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名,而Task也有自己的affinity属性,它的值等于它的根Activity的taskAffinity

LaunchMode应用场景
standard本应用内普通界面(很少自身跳转自身)
singleTop覆盖页面-逻辑不可控时使用-防止需要多次back:推送通知栏
singleTask应用主页、在线教室
singleInstance独立页面:来电显示、闹铃提醒(防止回退到自身)

注意:A -> B -> C -> D -> A -> B,A(Standard)和B(SingleTask)在一个任务栈,C(SingleTask)和D(SingleTask)在一个任务栈,返回时的顺序是B -> A -> A -> D -> C,需要考虑任务栈跳转的情况,优先清退当前任务栈

一开始,创建的Activity都会在创建它的Task中,并且大部分都在这里度过了它的整个生命,然而有一些情况,创建的Activity会被分配其它的Task中去,有的甚至,本来在一个Task中,之后出现了转移。我们首先分析一下android文档给我们介绍的两种情况

第一种情况:如果该Activity的allowTaskReparenting设置为true,当该Activity标记的task(Activity为根Activity)进入后台,当一个和它有相同affinity的Task进入前台时,该task会重新宿主,进入到该前台的task中(activity的launchMode设置为singleInstance则allowTaskReparenting不起作用)

第二种情况:如果加载某个Activity的intent,Flag被设置成FLAG_ACTIVITY_NEW_TASK时,它会首先检查是否存在与自己taskAffinity相同的Task,如果存在,那么它会直接宿主到该Task中,如果不存在则重新创建Task

1.android:allowTaskReparenting

2.android:alwaysRetainTaskState这个属性用来标记应用的task是否保持原来的状态,“true”表示总是保持,“false”表示不能够保证,默认为“false”。此属性只对task的根Activity起作用,其他的Activity都会被忽略默认情况下,如果一个应用在后台呆的太久例如30分钟,用户从主选单再次选择该应用时,系统就会对该应用的task进行清理,除了根Activity,其他Activity都会被清除出栈,但是如果在根Activity中设置了此属性之后,用户再次启动应用时,仍然可以看到上一次操作的界面

3.android:clearTaskOnLaunch这个属性用来标记是否从task清除除根Activity之外的所有的Activity,“true”表示清除,“false”表示不清除,默认为“false”。同样,这个属性也只对根Activity起作用,其他的Activity都会被忽略。allowTaskReparenting转移过来的activity也被清除掉(MA)

4.android:finishOnTaskLaunch这个属性和android:allowTaskReparenting属性相似,不同之处在于allowTaskReparenting属性是重新宿主到有共同affinity的task中,而finishOnTaskLaunch属性是销毁实例如果这个属性和android:allowTaskReparenting都设定为“true”则这个属性胜出

参考文档:

https://developer.android.com/guide/components/activities/tasks-and-back-stack

https://developer.android.com/guide/topics/manifest/activity-element#reparent

https://blog.csdn.net/hfy8971613/article/details/79683137

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little-sparrow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值