Activity的启动模式分析-之三

1.  Intent中影响Activity启动模式的FLAG

intent.setFlags(Intent.FLAG_ACTIVITY_????);

startActivity(intent);

1.   FLAG_ACTIVITY_SINGLE_TOP

Same as"singleTop"。

2.  FLAG_ACTIVITY_NO_HISTORY

也可以通过noHistory属性在manifest文件中指定:

<activity android:name=".ActivityB"

           android:label="ActivityB"

           android:noHistory="true">

</activity>

用于标记Activity是否会留下历史痕迹,即是否会在Activity stack中保留。

3.  FLAG_ACTIVITY_NEW_TASK

与“singleTask”的不同在于红色字体

当使用“FLAG_ACTIVITY_NEW_TASK”启动Activity时,系统首先会检查是否存在与该Activity的taskAffinity相同的task:

1.       如果task存在,直接实例化并入栈。所以,与“singleTask”不同的是,当Activity已经存在时,“FLAG_ACTIVITY_NEW_TASK”不会导致堆栈之上Activity的销毁和onNewIntent()的调用,,而是必定创建一个新的Activity实例。

2.      如果task不存在,那么就重新创建Task,并实例化入栈。

4.  FLAG_ACTIVITY_CLEAR_TOP

如果设置,并且这个Activity已经在当前的Task中运行,系统不再重新创建Activity的实例,而是将在这个Activity上方的所有Activity都关闭,然后调用它的onNewIntent()。

需要注意的是如果该Activity的启动模式是默认的“standard”,那么系统会把它先关闭然后重新启动一个新的实例来接收这个Intent。所以一般会和FLAG_ACTIVITY_SINGLE_TOP一起使用,这样的话就不会关闭已有实例,而是直接把这个Intent投递到当前这个实例的onNewIntent()中。

此外,FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK一起配合使用可以达到“singleTask”的效果。但是,和上面提到的情况一样,还是会有一点不同:如果该Activity的启动模式是默认的“standard”,那么系统会把它先关闭然后重新启动一个新的实例来接收这个Intent.

That's because a new instance isalways created for a new intent when the launch mode is "standard".这是因为系统保证了会为启动模式“standard”的Activity创建一个新的饿实例。

 

5.  FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

如果设置,将在Task的Activitystack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将被销毁(销毁的顺序不是按照出栈顺序,而是反序),以至于用户不能再返回到它们,但是可以回到之前的Activity。

如果stack中多个Activity都被设置了该标志位,那么将会以stack中最底部的那个Activity为准。

这在程序有分割点的时候很有用。例如,一个Email应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个 Activity应该作为Email应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面选择Email应用,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下次用户返回到Email程序时都将全部清除。

6.  FLAG_ACTIVITY_REORDER_TO_FRONT

如果设置,将使已经存在的Activity移动到stack的顶端,并调用onNewIntent()。

如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这个标志将被忽略。

假设当前栈中的内容是A,B,C,D,此时在D中通过该方式启动B,流程如下:

ActivityD: ====>onSaveInstanceState()

ActivityD:====> onPause()

ActivityB: ====> onNewIntent()

ActivityB:====> onRestart()

ActivityB:====> onStart()

ActivityB:====> onResume()

ActivityB:====> onPostResume()

ActivityD:====> onStop()

2.  manifest中<activity>的allowTaskReparenting属性

<activity android:name=".ActivityB"

           android:label="ActivityB"

           android:allowTaskReparenting="true">

</activity>

设置为true的作用是,当在应用A中启动了应用B的ActivityB,之后又通过Home键切出应用A,并启动应用B或者是将已经运行在后台的应用B带到前台,那么:

1.      如果将应用B带到前台,那么系统会将应用A中的所有的ActivityB都从堆栈中抽取出来,然后按照原来的次序放入到应用B的堆栈,然后显示最上面的ActivityB。

2.      如果是启动应用B,那么很惨的是,系统仍然会将之前在应用A中创建的ActivityB从堆栈中抽取出来,并整体放入应用B的堆栈,然后依次出栈destroy:

ActivityB: ====>onDestroy()

ActivityB:HashCode=1078795032 TaskId=129

ActivityB: ====>onDestroy()

ActivityB: HashCode=1078528752TaskId=129

ActivityA: ====> onCreate()

ActivityA: HashCode=1077874256 TaskId=130

ActivityA: <==== onCreate()

ActivityA: ====> onStart()

ActivityA: ====> onPostCreate()

ActivityA: ====> onResume()

ActivityA: ====> onPostResume()

例如,如果Email中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序提供的,但是,现在它作为Email Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当Email Task再次进入前台时,就看不到它了。

需要注意的是,由于启动模式为“singleTask”和 “singleInstance”的Activity只能位于自己的(taskAffinity匹配)task中,因此,重新宿主对它们实际上是不起作用的,因为重新宿主就是重新回到自己所属task(taskAffinity匹配)的怀抱,所以重新宿主实际上只对“standard”和“singleTop”模式有意义。

3.  manifest中<activity>的taskAffinity属性

<activity android:name=".ActivityB"

           android:label="ActivityB"

           android:taskAffinity="">

</activity>

taskAffinity属性指定Activity归属于哪一个task,属性值是字符串。

默认情况,一个应用程序中的所有Activity都拥有相同的affinity,默认值是从应用程序的设定继承下来(<application>元素的taskAffinity特性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。

可以通过taskAffinity来重组Activity,甚至可以把不同应用程序中定义的Activity放置到相同的Task中。

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

taskAffinity只有当<activity>中的allowTaskReparenting设置为true,或者是调用方将Intent的flag添加FLAG_ACTIVITY_NEW_TASK属性时才会生效。

taskAffinity决定两件事情:

1.      当intent包含FLAG_ACTIVITY_NEW_TASK时,Activity宿主的Task

2.      当<activity>中的TaskReparenting属性设置为"true"时,Activity重新宿主的Task

4.  Task中activity stack的维护策略

<activity android:name=".ActivityB"

           android:label="ActivityB"

           android:alwaysRetainTaskState="true"

           android:clearTaskOnLaunch="true"

           android:finishOnTaskLaunch="true">

</activity>

一般来说,当用户有一段时间没有访问Task时,例如30分钟,系统会对这个Task进行清理(从stack中删除位于根Activity之上的所有Activivity)。但是系统也允许我们通过以下属性来改变系统的默认行为:

1.   alwaysRetainTaskState

当设为“true”时,系统会原封不动的保持整个stack。

这个特性只对启动一个新的Task的Activity(根Activity)有意义;对Task中其它的Activity忽略。

2.  clearTaskOnLaunch

当这个值为“true”,每次用户重新启动这个Task时,都会从stack中删除位于根Activity之上的所有Activivity,并进入到它的根Activity中。

这个特性只对启动一个新的Task的Activity(根Activity)有意义;对Task中其它的Activity忽略。

3.  finishOnTaskLaunch

操作粒度是单个Activity,如果设置为“true”,当用户再次启动它的Task时,会从stack中销毁所对应的Activity。

如果这个特性和allowTaskReparenting都设定为“true”,那么这个特性胜出。Activity的affinity忽略。这个Activity不会重新宿主,而是会销毁。

1. 参考文档

http://1622511.blog.51cto.com/1612511/575080

 

http://winuxxan.blog.51cto.com/2779763/502523

 

http://winuxxan.blog.51cto.com/2779763/504047

 

http://winuxxan.blog.51cto.com/2779763/504835

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值