启动模式系列之:Activity启动模式(Standrd和SingleTop)
启动模式系列之:Activity启动模式(SingleTask)
启动模式系列之:Activity启动模式(SingleInstance)
解释:在启动单实例模式的Activity时,系统为其创建一个耽误的任务栈,以后每次都会使用这个单例,直到这个单例被摧毁。
与栈内复用模式不同,栈内复用模式是指定taskAffinity属性,所创建的任务栈并不独享,仍可添加其他的Activity,而单实例模式所创建的任务栈只含有这个实例。所以说是真正的单例模式。
操作示例:
MainActivity -> TestAActivity -> TestBActivity -> TestCActivity
adb记录:
Stack #1:
Task id #622
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
Hist #2: ActivityRecord{d8c8249 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t622}
Intent { flg=0x10400000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #1: ActivityRecord{1d98d9ee u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t622}
Intent { cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #0: ActivityRecord{c7511f7 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t622}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Task id #623
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
Hist #0: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Running activities (most recent first):
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Run #3: ActivityRecord{d8c8249 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t622}
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Run #2: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Run #1: ActivityRecord{1d98d9ee u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t622}
Run #0: ActivityRecord{c7511f7 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t622}
mResumedActivity: ActivityRecord{d8c8249 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t622}
首先,操作上此时的TestCActivity应该位于栈顶,从日志上也可以看出来,的确如此
再次,因为TestBActivity是SingleInstance模式,所以它在一个单独的任务栈中。从日志中可以看出来,TestBActivity确实在单独的任务栈TaskTecord中,但是这个任务栈的A值和系统默认任务栈的A值一样,都是包名,但是Task id不一样。这一点和我们的栈内复用设置taskAffinity不太一样,但是也是两个任务栈。
继续操作:
关闭TestCActivity
adb记录:
Stack #1:
Task id #622
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
Hist #1: ActivityRecord{1d98d9ee u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t622}
Intent { cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #0: ActivityRecord{c7511f7 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t622}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Task id #623
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
Hist #0: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Running activities (most recent first):
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=2}
Run #2: ActivityRecord{1d98d9ee u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t622}
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Run #1: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
TaskRecord{9d34a08 #622 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=2}
Run #0: ActivityRecord{c7511f7 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t622}
mResumedActivity: ActivityRecord{1d98d9ee u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t622}
从日志我们可以看出来,此时位于栈顶的的是TestActivity而不是,启动TestCActivity的TestBActivity。因为TestB位于自己的单独任务栈中,而MainActiity,TestAActivity,TestCActivity位于一个任务栈中。此时TestCActivity出栈,那么会切换到TestC所在的任务栈中,并显示这个栈中的栈顶Activity。
继续操作:
关闭TestAActivity,关闭MainActivity。
adb记录如下:
Stack #1:
Task id #623
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
Hist #0: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
ProcessRecord{1d3f65bb 23767:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Running activities (most recent first):
TaskRecord{19b525a1 #623 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Run #0: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
mResumedActivity: ActivityRecord{1fb47bb4 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t623}
理论上,我们推出MainActivity页面应该退回到桌面,但是此时我们能看到。其实是回到了TestBActivity。
以上我们可以得到一个结论就是,当调用到单实例的任务栈,单实例的任务栈(唯一)在调起其他Activity(进入系统默认任务栈)。在回退的时候,会优先退出当前页面所在的任务栈,然后在退出单实例的任务栈。
第二种操作:
MainActivity -> TestAActivity -> TestBActivity -> TestCActivity -> TestBActivity
adb记录如下:
Stack #1:
Task id #627
TaskRecord{3daa3fc3 #627 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
Hist #0: ActivityRecord{3a2df81 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t627}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
ProcessRecord{3715cf72 28186:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Task id #626
TaskRecord{34bcc040 #626 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity (has extras) }
Hist #2: ActivityRecord{285247f3 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t626}
Intent { flg=0x10400000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity }
ProcessRecord{3715cf72 28186:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #1: ActivityRecord{19c94413 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t626}
Intent { cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity }
ProcessRecord{3715cf72 28186:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #0: ActivityRecord{29ed325 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t626}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity (has extras) }
ProcessRecord{3715cf72 28186:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Running activities (most recent first):
TaskRecord{3daa3fc3 #627 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=1}
Run #3: ActivityRecord{3a2df81 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t627}
TaskRecord{34bcc040 #626 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Run #2: ActivityRecord{285247f3 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t626}
Run #1: ActivityRecord{19c94413 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t626}
Run #0: ActivityRecord{29ed325 u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t626}
mResumedActivity: ActivityRecord{3a2df81 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t627}
从上面日志我们可以看到。TestBActivity位于栈顶。而从Activity的生命周期日志我们也应该知道。TestC再次调起TestB。此时TestB并没有重复创建,而是复用的他单独任务栈的中实例。并将该实例至于栈顶。而此时就再次出现了。应用默认任务栈和单实例任务栈的再次前后台切换。
操作记录:
MainActivity -> TestAActivity -> TestBActivity -> TestCActivity
adb记录如下:
Stack #1:
Task id #637
TaskRecord{3de69dbf #637 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
Hist #2: ActivityRecord{d69a4a6 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t637}
Intent { flg=0x10400000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity }
ProcessRecord{2c4937de 31071:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #1: ActivityRecord{2430b46 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t637}
Intent { cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity }
ProcessRecord{2c4937de 31071:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Hist #0: ActivityRecord{71407be u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t637}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity }
ProcessRecord{2c4937de 31071:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Task id #638
TaskRecord{1ffb8c8c #638 A=org.wangchenlong.stack U=0 sz=1}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
Hist #0: ActivityRecord{9216615 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t638}
Intent { flg=0x10000000 cmp=org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity }
ProcessRecord{2c4937de 31071:org.wangchenlong.wcl_activity_launchmode_demo/u0a460}
Running activities (most recent first):
TaskRecord{3de69dbf #637 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Run #3: ActivityRecord{d69a4a6 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t637}
TaskRecord{1ffb8c8c #638 A=org.wangchenlong.stack U=0 sz=1}
Run #2: ActivityRecord{9216615 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestBActivity t638}
TaskRecord{3de69dbf #637 A=org.wangchenlong.wcl_activity_launchmode_demo U=0 sz=3}
Run #1: ActivityRecord{2430b46 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestAActivity t637}
Run #0: ActivityRecord{71407be u0 org.wangchenlong.wcl_activity_launchmode_demo/.MainActivity t637}
mResumedActivity: ActivityRecord{d69a4a6 u0 org.wangchenlong.wcl_activity_launchmode_demo/.TestCActivity t637}
从日志上我们可看出来,还是TestBActivity位于一个单独的任务栈,其他位于一个任务栈,不同于不设置taskAffinity属性的是。设置以后的TaskRecord的A值是我们设置的taskAffinity的值。其他跟默认不设置没有区别。有兴趣的同学可以试一下。
Android系统的任务栈体系分为三层:
启动模式本质上是为了避免相同Activity创建多个实例。避免系统资源的浪费。因此Android系统通过启动模式提供三种解决方案:
需要注意的是。SingleTask和SingleInstance都支持创建新的任务栈,这会涉及到前台任务栈和后台任务栈的关系。即一个Stack中有多个TaskRecord。
如果使用系统默认的后腿操作,即出栈操作,只有当前任务栈全部出栈,才会切换到其他任务栈,或者通过启动单实例模式的Activity才会触及切换任务栈。
另外还有一点,当单实例的任务栈位于系统默认任务栈上面的时候,此时如果点击手机Home键到桌面,然后再次点击应用图标,系统可能会认为是再次启动,直接切换到系统默认任务栈,此时显示的是系统任务栈栈顶的那个页面,而在退出这个栈所有的页面以后,并没有自动切换到单实例的任务栈,而是直接到桌面了。单实例的任务栈此时还在内存中。如果再次启动应用调用单实例的页面,会复用该页面并切换到单实例的任务栈中。
Demo下载:https://download.csdn.net/download/wangxp423/10767068
参考:《高级Android开发强化实战》
推荐:https://github.com/wangxp423 喜欢的小伙伴点一下 Star