Activity启动模式探索

Activity使我们在开发中最常用到的组件,除了坑爹的生命周期他的启动模式也是很重要的一个知识点。
Activity 一共有四种启动模式,分别为:standard,singleTop,singleTask,singleInstance。一下分别讨论着四种启动模式的异同和使用场景。

standard

standard是系统默认的启动模式,他的特点是每次启动Activity都会创建一个新的Activity实例。每个新的Activity既可以存在于同一个任务栈也可以存在于不同的任务栈下(任务栈接下来会浅谈),谁启动了这个standard模式的Activity,这个Activity就是出现在谁的栈内(singleInstance下令做讨论)。如果用ABCD的代表四个Activity的话我们启动了顺序A-B-C这个时候又启动了B那么栈内就会有ABCB四个Activity实例。ABCD在下文中代表四个Activity

singleTop

该模式下分类讨论,
①该Activity已经存在:
a.该Activity已经位于栈顶:这个Activity就不会被重新创建,并且会调用onNewIntent方法。举例说明,我们启动了ABCD四个Acitivity,这个时候D位于栈顶,并且D是singleTop模式,这个时候在D内重新启动D任务栈内结构仍为ABCD,但是这个时候D的onCreate,onStart不会被调用,onNewIntent被系统调起,我们可以再onNewIntent里面处理相关的信息。
b.该Activity不在栈顶:直接举例说明,C为singleTop模式,其他的为standar模式,栈内存在ABDC,C在栈顶,这个时候再去启动D就会重新创建一个新的Activity,栈内存在ABDCD五个Activity。
②该Activity不存在
会创建一个新的位于栈顶的Activity,其他同上。

singleTask

一个App不一定是只有一个任务栈干到死的,可能存在多个任务栈,而在singleTask模式的Activity只会存在一个栈内,分类讨论如下:
①该Activity在所在的栈都不存在:
创建一个新的栈然后将新Activity压入栈内。
②该Activity所在的任务栈存在:
a.栈在Activity不存在:创建新的Activity并压入栈内。
b.栈在Activity也存在:
1.该Activity在栈顶:Activity唤起并调用onNewIntent。
2.该Acitivity不在栈顶:该Activity被调至栈顶并调用onNewIntent。
注意:栈的结构是先进后出的,所谓的调至栈顶就是清空该Activity上面的Activity使用其暴露在顶部。(好黑暗/(ㄒoㄒ)/~~)
(上面提到的Acitivity所在的栈会在讨论完这四种模式后讨论)

好吧,显然这个singleTask模式是为处女座准备的。

举个栗子:栈S1存在ABC ,在C内启动singleTask模式的D,D所在的栈应该为S2,好了,开始套公式(敲黑板),
如果S2不存在,创建S2,并在S2内创建新的D;
如果S2存在,里面已经有了EF就是没有D,那么创建D,并压入S2栈顶;
如果S2存在,里面有了DEF,猥琐的D蹲在正好栈底部,那么D上面的EF就会被赶出S2栈,使D出现在栈顶,并调用D的onNewIntent方法。

综上所述:singleTask是一个任务栈内复用的模式。

PS:启动一个新的任务栈的singleTaskActivity系统动画会和standard模式下一键跳转不一样。不知道是不是系统的问题,还是Android对于任务栈就是这么定义的。

singleInstance

顾名思义,单例模式...
这种模式下和上述的singleTask很接近,唯一不一样的是,在singleTask模式下的Activity是允许大家住一间屋的,但是它有事的时候你们都得让路,它是不会重建的。而这个singleInstance模式的Activity简直就是混蛋的孤家寡人,它不允许它住的屋子里面有人...也就是说singleInstance自己拥有一个任务栈,栈内只有他自己。

我们上面提到在standard之下跳转,在哪个栈内跳转就standard模式的Activity就会出现的谁的栈内,但是基于上面singleInstance的孤家寡人理论这两个显然是矛盾的,本着知行合一,做一个实现,新建ABC三个Activity,C为singleTask,A->B->C 然后继续跳转到A,这个是时候back,会发现显示了B,并没有显示C,接着back会显示A,再BACK显示C,在C就退出应用了。而且在C相邻Activity会明显发现动画不一样。

这是我们看到的情况,接下来我们用 abd shell dumpsys activity命令,找到输出

TaskRecord{85124cb #1461 A=com.maomibox.myapplication U=0 StackId=1 sz=3}
        Run #16: ActivityRecord{7733e23 u0 com.maomibox.myapplication/.A t1461}
TaskRecord{e348f76 #1462 A=com.maomibox.myapplication U=0 StackId=1 sz=1}
        Run #15: ActivityRecord{6c5074a u0 com.maomibox.myapplication/.C t1462}
TaskRecord{85124cb #1461 A=com.maomibox.myapplication U=0 StackId=1 sz=3}
        Run #14: ActivityRecord{8047354 u0 com.maomibox.myapplication/.B t1461}
        Run #13: ActivityRecord{9e18691 u0 com.maomibox.myapplication/.A t1461}

会发现id为85124cb只有ABAAcitivity,C存在于 id为e348f76 的栈内,也就是说C所在的栈内是有他自己,A也并没有像上文说的standard一样出现在C所在的栈内。在栈85124cb全部退出后,执行e348f76 栈的退出,最终退出应用。

啥是任务栈

上面提到了那么多任务栈,这个任务栈是啥?
栈是一种先进后出的结构,任务栈就是存放Activity的地方,standard模式下只有一个任务栈,而在singleTask模式下并搭配上taskAffinity属性则会新开一个任务栈,singleInstance自带Buff,自己会创建一个任务栈,如果在singleTask下不指定taskAffinity那么就相当于啥都没做,还是在默认栈内。给activity指定任务栈如下

        

上文提到的“所在的栈”就是这个com.demo.c,C就运行在这个栈内。
taskAffinity属性和signleTask启动模式或者和allowTaskReparenting搭配才有用没其他情况下毛用没有(有待验证)。

Activity FLAGS

Activity的Flag很多,Intent.FLAG_ACTIVITY_ IDE会联想出来很多,列举几个常用的如下:
FLAG_ACTIVITY_NEW_TASK
同singleTask
FLAG_ACTIVITY_SINGLE_TOP
同singleTop
FLAG_ACTIVITY_CLEAR_TOP
该FLAG下同FLAG_ACTIVITY_NEW_TASK搭配下和之前将的清光栈暴露Acitivity类似。

使用场景(本段来自互联网)自己体会吧...

standard: 适合多个实例存在的情况,比如,发邮件页面。
singleTop: 适合接收通知内容显示页面。例如,某些应用会为用户推送一些消息通知,当用户从任务栏中进入查看消息内容界面时,如果设置为singleTop时,这样每次行为都使用同一个实例,用户点击返回时不会存在多个消息页面的情况。
singleTask: 适合使用在一个程序的主界面。
singleInstance: 使用较少,比如一些launchAPP可能会使用到。

你可能感兴趣的:(Activity启动模式探索)