Android启动模式和TaskAffinity
任务和返回栈
应用通常包含多个 Activity ,每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity,一个 Activity 可以启动设备上其他应用中的 Activity,即使两个 Activity 可能来自不同的应用,但是 Android 仍会将 Activity 保留在相同的任务中,以维护这种无缝的用户体验。这里所说的任务就是指在执行特定作业时与用户交互的一系列 Activity,这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。返回栈以“后进先出”对象结构运行。
查看activity Task栈的情况 adb命令:
adb shell dumpsys activity activities
启动模式
一直启动activity系统会创建多个实例,提供提供启动模式来修改系统的默认行为
1 | adnroid:launchMode="standard" or "1" |
standard默认模式
系统每启动一次 Activity 的任务就会创建一次 Activity 的新实例并向其传送 Intent。每个实例可以属于不同的任务,一个任务也能拥有多个实例。这种模式的 Activity 被创建时它的 onCreate、onStart 都会被调用。
singleTop栈顶复用模式
如果当前任务的顶部已存在Activity的一个实例,则系统会通过调用该实例onNewIntent()方法向其传送Intent,而不是创建Activity的新实例。当返回栈顶部不是所需Activity的现有实例,Activity可以被多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。这个 Activity 的 onCreate、onStart 不会被系统调用,因为它并没有发生改变。
singleTask 栈内复用模式
单例模式下,只要Acivity在一个栈中存在,那么多次启动次Activity都不会创建新实例,但是会通过回调onNewIntent来启动。
当具有一个singleTask模式的Activity请求启动后,比如Activity A,系统会先寻找是否存在A想要的任务栈(taskAffinity属性),如果不存在,就重新创建一个任务栈,然后创建 A 的实例后把 A 放到栈中。如果存在 A 所需的任务栈,这时要看 A 是否在栈中有实例存在,如果有实例存在,那么系统就会把 A 调到栈顶并调用它的 onNewIntent 方法,如果实例不存在,就创建 A 的实例并把 A 压入栈中 。
关于上文中所说的想要的任务栈
,指的是 taskAffinity 属性。
singleTask 默认有 clearTop 的效果,会导致栈内所有在它上面的 Activity 全部出栈
singleInstance单实例模式
与 singleTask 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。也就是有此种模式的 Activity 只能单独地位于一个任务栈中
如果已经创建过,则调用 onNewIntent 方法 不会调用 onCreate 和 onStart
taskAffinity属性
taskAffinity 属性主要和 singleTask 或者 allowTaskReparenting 属性配对使用,在其他情况下没有意义。
当设置了taskAffinity属性那么这个 Activity 在被创建时就会运行在和 taskAffinity 名字相同的任务栈中,如果没有,则新建 taskAffinity 指定的任务栈,并将 Activity 放入该栈中。
总结
launchMode | 使用场景 |
---|---|
singleTop | 适合启动同类型的 Activity,例如接收通知启动的内容显示页面 |
singleTask | 适合作为程序入口 |
singleInstance | 适合需要与程序分离开的页面,例如闹铃的响铃界面 |
onNewIntent()方法
当Acivity已经被启动且处于当前应用返回栈中,activity的LaunchMode为SingleTop、SingleTask、SingleInstance时会被调用。
当Acivityde LaunchMode为singleTop时
当需要再次响应次Activity启动需求时,会复用栈顶的已有的Activity,还会调用onNewIntent()方法,并且,再次接受新发来的intent()一定会先执行onPause()方法。
生命周期顺序:onCreate->onStart->onResume->onPause->onNewIntent->onResume
当Activity的LaunchMode为SingleTask,SingleInstance
生命周期调用顺序:onCreate -> onStart -> onResume -> …… -> onPause -> onStop -> onNewIntent -> onRestart -> onStart -> onResume
onNewIntent()中的陷阱:
当多次启动一个栈唯一模式下的activity时,在onNewIntent()里面的getIntent()得到的intent感觉都是第一次的那个数据。
在这儿会有个陷阱,因为它就是会返回第一个intent的数据,就是这个坑。
原因是因为没有在onNewIntent()
里面设置setIntent()
,即将最新的intent
设置在这个activity实例中。
1 | @Override |
参考链接:https://www.cnblogs.com/pshell/p/7979649.html
https://www.jianshu.com/p/2c73be80ce8d
https://blog.csdn.net/goodlixueyong/article/details/49620667
https://juejin.cn/post/6844904007085850631