天天看点

activity的启动模式和栈管理 1.什么是栈 3.Task 4.Activity启动模式 5.Activity栈和Task联系 6.Intent Flags  7.Activity相关属性taskAffinity

 在学习android的过程中,intent是我们最常用android用于进程内或进程间通信的机制,其底层的通信是以binder机制实现的,在物理层则是通过共享内存的方式实现的。

    intent主要用于2种情景下:(1)发起意图

 (2)广播

    它的属性有:componentname,action,data,category,extras,flags等,通常情况下,进行intent的匹配涉及到3个属性:action,data,category。这些东西都需要了解才能对它有个深入的体会。

    下面我就根据近期学习,总结记录下activity启动模式

及 intent flags 与 栈 的关联分析。

文章结构:

1.什么是栈

2.activity栈

3.task

4.activity启动模式

5.activity栈和task联系

6.intent flags 

7.activity相关属性taskaffinity

task是与activity相关的一个重要概念,它密切联系着activity栈,它简单的说,就是一组以栈的模式聚集在一起的activity组件集合。(这里只提它和activity的启动模式来讲)

属性:android:launchmode  

作用:用于指示activity如何启动。

描述:这里有四种模式,与intent对象中的activity flags的属性(flag_activity_*变量)共同作用,来决定activity如何启动来处理intent。

四种模式:

    "standard"  --默认模式

    "singletop"

    "singletask"

    "singleinstance"

以下举例说明它们的区别:

standard:activity的默认加载方法,该方法会通过跳转到一个新的activity,同时将该实例压入到栈中(不管该activity是否已经存在在task栈中,都是采用new操作)。例如:

栈中顺序是a b c d ,此时d通过intent跳转到a,那么栈中结构就变成 a b c d a ,点击返回按钮的 显示顺序是 d c b a,依次摧毁。

singletop:singletop模式下,当前activity

d位于栈顶的时候,如果通过intent跳转到它本身的activity (即d),那么不会重新创建一个新的d实例,所以栈中的结构依旧为a b c d,如果跳转到b,那么由于b不处于栈顶,所以会新建一个b实例并压入到栈中,结构就变成了a b c d b。

singletask:singletask模式下,task栈中只能有一个对应activity的实例。例如:现在栈的结构为:a

b c d。此时d通过intent跳转到b,则栈的结构变成了:a b。其中的c和d被栈弹出销毁了,也就是说位于b之上的实例都被销毁了。

singleinstance:singleinstance模式下,会将打开的activity压入一个新建的任务栈中。例如:task栈1中结构为:a

b c ,c通过intent跳转到了d(d的模式为singleinstance),那么则会新建一个task 栈2,栈1中结构依旧为a b c,栈2中结构为d,此时屏幕中显示d,之后d通过intent跳转到d,栈2中不会压入新的d,所以2个栈中的情况没发生改变。如果d跳转到了c,那么就会根据c对应的launchmode的在栈1中进行对应的操作,c如果为standard,那么d跳转到c,栈1的结构为a

b c c ,此时点击返回按钮,还是在c,栈1的结构变为a b c,而不会回到d。

task简单的就是一组以栈的模式聚集在一起的activity组件集合,类似于一个填充了activity的容器,最先加入的activity会处于容器最下面,最后加入的处于容器最上面,而从task中取出activity是从最顶端先取出,最后取出的是最开始添加activity,这就是后进先出(last

in first out)模式,而activity在task中的顺序是可以控制的,在activity跳转时用到intent flag可以设置新建activity的创建方式(这里就涉及到了intent flag的使用)。

flags: 表示intent的标志位,常用于activity的场景中,它和activity的启动模式有着密切的联系。

下面列举的是和本文主题相关的flags属性:

intent.flag_activity_new_task

(默认)

默认的跳转类型,它会重新创建一个新的activity,不过与这种情况,比如说task1中有a,b,c三个activity,此时在c中启动d的话,如果在androidmanifest.xml文件中给d添加了affinity的值和task中的不一样的话,则会在新标记的affinity所存在的task中压入这个activity。如果是默认的或者指定的affinity和task一样的话,就和标准模式一样了启动一个新的activity.

flag_activity_single_top

这个flag就相当于启动模式中的singletop,例如:原来栈中结构是a b c d,在d中启动d,栈中的情况还是a,b,c,d。

flag_activity_clear_top

这个flag就相当于启动模式中的singletask,这种flag启动的activity会把要启动的activity之上的activity全部弹出栈空间。例如:原来栈中的结构是a

b c d ,从d中跳转到b,栈中的结构就变为了a b了。(这个方法可以用来关闭多个activity,之后的一篇博文里面会提到)

flag_activity_brought_to_front

这个网上很多人是这样写的。如果activity在task存在,拿到最顶端,不会启动新的activity。这个有可能会误导大家! 他这个flag其实是这个意思!比如说我现在有a,在a中启动b,此时在A中intent中加上这个标记。此时b就是以flag_activity_brought_to_front方式启动,此时在b中再启动c,d(正常启动c,d),如果这个时候在d中再启动b,这个时候最后的栈的情况是

a,c,d,b。如果在a,b,c,d正常启动的话,不管b有没有用flag_activity_brought_to_front启动,此时在d中启动b的话,还是会变成a,c,d,b的。

flag_activity_no_user_action

onuserleavehint()作为activity周期的一部分,它在activity因为用户要跳转到别的activity而要退到background时使用。比如,在用户按下home键,它将被调用。比如有电话进来(不属于用户的选择),它就不会被调用。

那么系统如何区分让当前activity退到background时使用是用户的选择?

它是根据促使当前activity退到background的那个新启动的activity的intent里是否有flag_activity_no_user_action来确定的。

注意:调用finish()使该activity销毁时不会调用该函数

flag_activity_no_history

意思就是说用这个flag启动的activity,一旦退出,它不会存在于栈中,比方说!原来是a,b,c这个时候再c中以这个flag启动d的,d再启动e,这个时候栈中情况为a,b,c,e。

activity

中的 android:taskaffinity 这个属性介绍:

   activity为task拥有的一个affinity。拥有相同的affinity的activity理论上属于相同的task(在用户的角度是相同的“应用程序”)。task的affinity是由它的根activity决定的。 

   affinity决定两件事情——activity重新宿主的task(参考allowtaskreparenting特性)和使用flag_activity_new_task标志启动的activity宿主的task。

    默认情况,一个应用程序中的所有activity都拥有相同的affinity。捏可以设定这个特性来重组它们,甚至可以把不同应用程序中定义的activity放置到相同的task中。为了明确activity不宿主特定的task,设定该特性为空的字符串。

    如果这个特性没有设置,activity将从应用程序的设定那里继承下来(参考<application>元素的taskaffinity特性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。

注:以上的android:taskaffinity只有通过标志位为flag_activity_new_task的intent启动activity时,该activity的这个属性才会生效,系统才会将具有相同task亲和力的task切换到前台,然后启动该activity,否则该activity仍然运行在启动它的task中。

  上面总结了下activity启动模式 及 intent flags 与 栈 的关联分析,便于之后一篇文章中跳转模式的了解使用。

继续阅读