Android得启动模式
Android得启动模式launchMode 分为四中:
standar : 默认W为该启动模式,每当发送一个intent请求打开activity时,都会创建一个新得activit实例。
比如 Activity A,B, C, D 四个Activity,当前栈为 A -> B -> C -> D (D 为栈顶) ,当在D 得时候启动B ,那么返回栈得顺序就变成
A -> B -> C -> D -> B 了。
singleTop : singleTop 和standar 差不多,使用singleTop也会创建多个实例,唯一不同得就是,如果调用目标Activity已经位于调用者得得栈顶了,则不创建新得实例,并调用这个实例得onNewIntent方法。
比如 当前栈为 A -> B -> C -> D (D 为栈顶) 当在D 得时候启动D得时候,当前栈顶为 A -> B -> C -> D,当当在D 得时候启动B, 那么返回栈得顺序就变成 A -> B -> C -> D -> B 了。
singleTask : 启动得activity在系统中只会存在一个实例,如果这个实例已经存在,Intent 就会通过 onNewIntent 传递到Acticity,并且将返回栈中得activity之上得activity清除,如果不存在则会创建新得Activity实例.
比如 : 当前栈为 A -> B -> C -> D (D 为栈顶) ,当D 启动 E 时,当前栈为 A -> B -> C -> D -> E ,如果启动得是A ,那么当前栈为 A ,其他得Activity实例会被销毁掉。
singleInstance : 和singleTo 一样,在系统中只会存在一个实例,唯一区别是系统不会在singleInstance activity得栈中启动任何其他得activty,singleInstance activity 栈中仅仅只能有该actvity得实例,其他任何在这个actvity中启动得activty都会在其他栈中打开。
A -> B -> C(C 为栈顶) D 得启动模式为singleInstance 那么在C 中启动D 实例,当前栈就是 A -> B -> C 和另外一个栈 D,
然后在D 中启动C(standar模式),则栈就是 A -> B -> C ->C 和 D两个栈了。
Intent 中设置得flag得启动模式。
android: taskAffinit :与Activity有亲和关系,确定亲和关系是有Activity 更改到父项任务和通过FLAG_ACTIVITY_NEW_TASK 标志启动 Activity 时将用来容纳它的任务。默认情况下,应用中得所有Activity都有相同得亲和关系,可以通过设置该属性来以不同得方式组合,
在使用得过程中,对于非Activity启动的Activity(比如Service中启动的Activity)需要显示的设置Intent.FLAG_ACTIVITY_NEW_TASK,而singleTask及singleInstance在AMS中被预处理后,隐形的设置了Intent.FLAG_ACTIVITY_NEW_TASK,而启动模式是standard及singletTop的Activity不会被设置Intent.FLAG_ACTIVITY_NEW_TASK,除非通过显示的intent setFlag进行设置。
以Service启动Activity为例:
Intent intent = new Intent(BackGroundService.this, A.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
如果目标Activity实例或者Task不存在,则一定会新建Activity,并将目标Task移动到前台,但是如果Activity存在,却并不一定复用,也不一定可见。这里假定A是standard的Activity,如果已经有一个A实例,并且所在的堆栈的taskAffinity跟A的taskAffinity一致,这个时候要看这个task的根Activity是不是A,如果是A,还要看A的intent是不是跟当前的启动的intent相等,如果都满足,只要将task可见即可。否则,就需要新建A,并根据A的task栈的存在情况而选择直接入栈还是新建栈。但是,如果Intent想要的启动的Activity的目标堆栈存在,那就将整个堆栈往前迁移,如果位于顶部的Task栈正好是目标Activity的Task栈,那就不做任何处理,连onNewIntent都不会回调,怎么判断目标的Activity的Task栈同找到的栈一致呢?如果找不到目标Task自然会启动Task,如果目标task栈根Activity得intent同新要启动得Activity相同,就不启动新得Activty,否则启动Activity。
(图片来自https://juejin.im/post/59b0f25551882538cb1ecae1 )
FLAG_ACTIVITY_CLEAR_TASK : 如果在调用startActivity时传递这个标记,该task栈中的其他activity会先被清空,然后该activity在该task中启动,也就是说,这个新启动的activity变为了这个空task的根activity。所有老的activity都结束掉。该标志必须和FLAG_ACTIVITY_NEW_TASK一起使用。
(图片来自https://juejin.im/post/59b0f25551882538cb1ecae1 )
FLAG_ACTIVITY_CLEAR_TOP : 如果该activity已经在task中存在,并且设置了该task,系统不会启动新的 Activity 实例,会将task栈里该Activity之上的所有Activity一律结束掉,然后将Intent发给这个已存在的Activity。Activity收到 Intent之后,或者在onNewIntent()里做下一步的处理,或者自行结束然后重新创建自己。如果 Activity 在 AndroidMainifest.xml 里将启动模式设置成默认standard模式,并且 Intent 里也没有设置 FLAG_ACTIVITY_SINGLE_TOP,那么他将会结束并且重启;否则则会传递到onNewIntent方法,FLAG_ACTIVITY_CLEAR_TOP 还可以和 FLAG_ACTIVITY_NEW_TASK 配合使用,用来启动一个task栈的根activity,他将会把该栈清空为根状态
(图片来自https://juejin.im/post/59b0f25551882538cb1ecae1 )
Android 有多个版本,其中得Flag 又有不同,要理解各种组合是很困难得,只能先理解经常使用得几个flag。