【转】Activity的launchMode分析 及 Intent.FLAG_NEW_TASK详解

Activity的启动模式共有四种,分别如下:

1、standard

2、singleTop

3、singleTask

4、singleInstance

这里我们分两种情况讨论上述四种启动模式:app内和app之间

首先讨论app内

standard:不论当前任务栈中是否存在该Activity,都会新建一个Activity,如 任务栈为A B,要启动B 那么任务栈为 A B B

singleTop:如果当前要创建的Activity就在任务栈的顶端,那么不会创建新的Activity,仅仅调用Activity的onNewIntent方法,如果不在栈顶(或者栈中没有该Activity),那么还是会创建新的Activity,如任务栈为A B 启动B  任务栈变为 A B 如果 启动A 那么任务栈为 A B A (如新闻推送,10个新闻推送也只会调用一个Activity 10个页面是不是会很烦?)

singleTask:如果当前任务中存在要启动的Activity,那么就不会创建新的Activity,如果不存在就会创建新的Activity,如任务栈为 A B C,启动B ,那么任务栈就会变为A B 即启动该activity时永远放在栈顶并销毁其栈上面的activity (如启动页,首页(返回的时候))

singleInstance:将一个Activity的launchMode设置为该值时,表明这个Activity独自占用一个任务队列,这个队列中不允许加入其他的Activity (闹钟等独立应用)

不同的app之间:

既然在不同的app之间,那么就说明是有两个任务栈,并且有一个处理前台,一个运行在后台

standard:当前台的Activity启动后台任务的Activity,不管这个Activity在后台任务栈中是否已经存在,都会创建一个新的Activity,并将它加入前台的任务栈中

singleTop:如果前台的Activity启动后台任务的Activity,并且这个Activity已经在后台任务的栈顶,和app内不同的是,这里还不能确定是否会创建新的Activity,这里还需要看启动Activity的Intent里面是否有Intent.FLAG_ACTIVITY_NEW_TASK,如果此标记,那么就会将后台的任务队列移动到前端,如 前端任务栈 A B 后端任务栈 E F C,现在前端需要启动一个C,如果有Intent.FLAG_ACTIVITY_NEW_TASK,那么后端任务栈就会移到前端(并调用C的onNewIntent,见下文FLAG_ACTIVITY_NEW_TASK的分析),前端栈退居后端。如果没有这个标记,那么仅仅就是在前端任务栈中创建一个新的Activity C。

singleTask:如果前台的Activity启动后台任务的Activity,不管这个Activity是否在栈顶,都会将后台的任务栈移到前台,前台任务栈移至后台。这里不需要考虑标记问题,因为被启动的Activity如果是singleTask,那么自动在启动Activity的intent中加入上述标记。

singleInstance:如果前台Activity启动后台任务的Activity,如果后台任务栈中已经有该Activity,那么就会调用该Activity的onNewIntent,并且后台任务还是在后台。如果后台任务栈中没有该Activity,那么会重新创建一个Acitivyt,并单独放入一个任务栈,其实在启动该Acitivity的Intent中也会加入上述标记

Task是包含一系列Activity的堆栈, 遵循先进后出原则.

Task默认行为:

(1) 前提: Activity A和Activity B在同一个应用中.

操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B(堆栈状态: AB), 按下BACK返回键(堆栈状态: A).

(2) 前提: Activity A和Activity B在同一个应用中, 应用名称为"TaskOne应用".

操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity B(TaskA堆栈状态: AB), 长按Home键, 返回Launcher, 启动其它应用(如:电子书),

开僻一个新Task堆栈, 命名: TaskB, 长按Home健, 返回Launcher, 单击"TaskOne应用"图标, 此时TaskA堆栈返回前台,

Activity B为栈顶应用, 供用户使用.

(3) 前提: Activity A在名称为"TaskOne应用"的应用中, Activity C在名称为"TaskTwo应用"的应用中.

操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity C(TaskA堆栈状态: AC),长按Home键, 返回Launcher, 启动"TaskTwo应用"即Activity C,

开僻新的Task堆栈, 命名为TaskB, 按BACK键返回Launcher, 单击"TaskOne应用"图标, 此时TaskA堆栈返回前台,

Activity C为栈顶应用, 供用户使用.

Intent FLAG介绍:

(1) FLAG_ACTIVITY_NEW_TASK: 设置此状态,记住以下原则,首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的activity的亲和性一样,所以下面的a情况会在同一个栈中),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity

a. 前提: Activity A和Activity B在同一个应用中.

操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B, 启动Activity B的Intent的Flag设为

FLAG_ACTIVITY_NEW_TASK, Activity B被压入Activity A所在堆栈(堆栈状态: AB).

原因: 默认情况下同一个应用中的所有Activity拥有相同的关系(taskAffinity).

b. 前提: Activity A在名称为"TaskOne应用"的应用中, Activity C和Activity D在名称为"TaskTwo应用"的应用中.

操作1: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity C, 启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,

Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C), 长按Home键, 选择TaskA,

Activity A回到前台, 再次启动Activity C(两种情况1.从桌面启动;2.从Activity A启动,两种情况一样), 这时TaskB回到前台, Activity C显示, 供用户使用, 即:

包含FLAG_ACTIVITY_NEW_TASK的Intent启动Activity的Task正在运行, 则不会为该Activity创建新的Task,

而是将原有的Task返回到前台显示.

操作2: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity C,启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,

Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C),  在Activity C中启动

Activity D(TaskB的状态: CD) 长按Home键, 选择TaskA, Activity A回到前台, 再次启动Activity C(从桌面或者ActivityA启动,也是一样的),

这时TaskB回到前台, Activity D显示,供用户使用.说明了在此种情况下设置FLAG_ACTIVITY_NEW_TASK后,会先查找是不是有Activity C存在的栈,根据亲和             性(taskAffinity),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的顺序不变

(2) FLAG_ACTIVITY_CLEAR_TOP:

前提: Activity A, Activity B, Activity C和Activity D在同一个应用中.

操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B(堆栈状态: AB), 在Activity B中启动

Activity C(堆栈状态: ABC), 在Activity C中启动Activity D(堆栈状态: ABCD), 在Activity D中启动Activity B,

启动Activity B的Intent的Flag设置为FLAG_ACTIVITY_CLEAR_TOP, (堆栈状态: AB).

(3) FLAG_ACTIVITY_BROUGHT_TO_FRONT:

前提: Activity A在名称为"TaskOne应用"的应用中, Activity C和Activity D在名称为"TaskTwo应用"的应用中.

操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity C,启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,

Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C), 在Activity C中启动

Activity D(TaskB的堆栈状态: CD), 长按Home键, 选择TaskA, Activity A回到前台, 在Activity A中再次启动Activity C,

在启动Activity C的Intent中设置Flag为FLAG_ACTIVITY_BROUGHT_TO_FRONT, TaskB回到前台,

Activity C显示, (TaskB的堆栈状态: C).

(4) FLAG_ACTIVITY_MULTIPLE_TASK:

与FLAG_ACTIVITY_NEW_TASK结合使用, 首先在Intent中设置FLAG_ACTIVITY_NEW_TASK, 打开Activity,

则启动一个新Task, 接着在Intent中设置FLAG_ACTIVITY_MULTIPLE_TASK, 再次打开同一个Activity,则还会新启动一个Task.

(5) FLAG_ACTIVITY_SINGLE_TOP:

当前Task堆栈中存在ABCD四个Activity, A是栈顶Activity, D为栈底Activity, 存在打开A的Intent中设置了

FLAG_ACTIVITY_SINGLE_TOP标志, 则会使用栈顶A, 而不会从新New A.

(6) FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:

   一般与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET结合使用,如果设置该属性,这个activity将在一个新的task中启动或者或者被带到一个已经存在的task的顶部,这时这个activity将会作为这个task的首个页面加载。将会导致与这个应用具有相同亲和力的task处于一个合适的状态(移动activity到这个task或者从中移出),或者简单的重置这个task到它的初始状态

   FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:在当前的Task堆栈中设置一个还原点,当带有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求启动这个堆栈时(典型的例子是用户从桌面再次启动这个应用),还原点之上包括这个应用将会被清除。应用场景:在email程序中预览图片时,会启动图片观览的actvity,当用户离开email处理其他事情,然后下次再次从home进入email时,我们呈现给用户的应该是上次email的会话,而不是图片观览,这样才不会给用户造成困惑。

例: 存在Activity A, Activity B, Activity C, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),

在Activity A中启动Activity B(TaskA堆栈状态: AB), 接着Activity B启动Activity C(TaskA堆栈状态: ABC),

启动Activity C的Intent中设置FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET标题, 这样TaskA中有一个还原点,

当有包含FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求TaskA堆栈时(比如请求Activity A)

系统就会将还原点以上的Activity清除, TaskA堆栈中只剩下了AB.

taskAffinity属性:

(1) taskAffinity属性应和FLAG_ACTIVITY_NEW_TASK标志及allowTaskReparenting属性结合使用, 如果只使用taskAffinity属性,

请参考上面Task默认的行为.

(2) 与FLAG_ACTIVITY_NEW_TASK标志结合:

a. 前题: Activity A和Activity B在同一个应用中, Activity A与Activity B设置不同的taskAffinity属性.

操作: Activity A启动开僻Task堆栈,命名为TaskA(TaskA堆栈状态: A), 在Activity A中启动Activity B, 启动Activity B

的Intent中设置FLAG_ACTIVITY_NEW_TASK标志,这时系统会新开僻一个Task堆栈,TaskB(TaskB堆栈状态: B).

b. 前题: Activity A在"TaskOne应用"中, Activity C在"TaskTwo应用"中, Activity A和ActivityC设置了相同的taskAffinity属性.

操作: Activity A启动开僻Task堆栈,命名为TaskA(TaskA堆栈状态: A), 在Activity A中启动Activity C, 启动Activity C的

Intent中设置FLAG_ACTIVITY_NEW_TASK标志,这时Activity C会压入与Activity A堆栈相同的TaskA堆栈(TaskA堆栈状态: AC).

(3) 与allowTaskReparenting属性:

例: 在"TaskOne应用"中有一个天气预报Activity A, Activity A与"TaskOne应用"中的其它Activity有默认的关系

(taskAffinity属性都没有设置), 并且allowTaskReparenting属性设置为true, 现在存在一个"TaskTwo应用

"启动了"TaskOne应用"中的天气预报Activity A,  这时Activity A与"TaskTwo应用"中的Activity在同一个Task,

命名这个Task堆栈为TaskA, 这时"TaskOne应用"启动, 并且又打开发天气预报Activity A, 这时Activity A会从TaskA堆栈中转移到

"TaskOne应用"所在的堆栈, 即Activity A可以在多个堆栈中来回转移.       
alwaysRetainTaskState属性:

如果Task堆栈中的Root Activity设置了此属性值为true, 不管出现任何情况, 一直会保留Task栈中Activity的状态.

clearTaskOnLaunch属性:

如果Task堆栈中的Root Activity设置了此属性值为true, 只要你一离开这个Task栈, 则系统会马上清理除了Root Activity的全部Activity.

finishOnTaskLaunch属性:

如果某Activity设置了finishOnTaskLaunch属性, 只要你一离开这个Task栈, 则系统会马上清除这个Activity,

不管这个Activity在堆栈的任何位置.

时间: 2024-10-27 07:29:24

【转】Activity的launchMode分析 及 Intent.FLAG_NEW_TASK详解的相关文章

Activity的启动模式 4种launchMode Intent.FLAG_NEW_TASK 详解

参考:http://blog.csdn.net/liuhe688/article/details/6754323 了解android开发的同学都知道 android开发 主要内容就是四大组件:Activity. BroadCastReceiver.Service.ContentProvider 而Activity又是重中之重  所以了解Activity的生命周期,启动模式等对我们来说是非常有必要的 .本文主要讲讲Activity的启动模式及其相关概念. Activity的启动模式主要四种,sta

Android Intent.FLAG_NEW_TASK详解,包括其他的标记的一些解释

本文大部分参考自 http://blog.csdn.net/mayingcai1987/article/details/6200909 ,对原文中的讲解FLAG_NEW_TASK地方加了一些自己的观点,用红色标记 1. Task是包含一系列Activity的堆栈, 遵循先进后出原则. 2. Task默认行为: (1) 前提: Activity A和Activity B在同一个应用中. 操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activit

android源码分析 android toast使用详解 toast自定义

在安卓开发过程中,toast使我们经常使用的一个类,当我们需要向用户传达一些信息,但是不需要和用户交互时,该方式就是一种十分恰当的途径. 我们习惯了这样使用toast:Toast.makeText(Context context, String info, int duration).show();该方法是 系统为我们提供的一个方便的创建toast对象的静态方法,其内部依然是调用toast的相关方法完成.下面 就从其源码对该类的实现做一个分析 在toast类中,最重要的用于显示该toast的sh

Java性能分析之线程栈详解(下)

Java性能分析之线程栈详解(下) 转载自:微信公众号"测试那点事儿" 结合jstack结果对线程状态详解 上篇文章详细介绍了线程栈的作用.状态.任何查看理解,本篇文章结合jstack工具来查看线程状态,并列出重点关注目标.Jstack是常用的排查工具,它能输出在某一个时间,Java进程中所有线程的状态,很多时候这些状态信息能给我们的排查工作带来有用的线索. Jstack的输出中,Java线程状态主要是以下几种: 1.BLOCKED 线程在等待monitor锁(synchronized

Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解

概况 Android在4.3的版本中(即API 18)加入了NotificationListenerService,根据SDK的描述(AndroidDeveloper)可以知道,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法.同时在Android 4.4 中新增了Notification.extras 字段,也就是说可以使用NotificationListenerService获取系统通知具体信息,这在以前是需要用反射来实现的. 转载请

Android中Activity运行时屏幕方向与显示方式详解

现在我们的手机一般都内置有方向感应器,手机屏幕会根据所处位置自动进行横竖屏切换(前提是未锁定屏幕方向).但有时我们的应用程序仅限在横屏或者竖屏状态下才可以运行,此时我们需要锁定该程序Activity运行时的屏幕方向.还有就是在我们用手机观看视频时,随意的进行横竖屏切换,但播放进度不会随着屏幕的转换而从头开始播放,为了实现这个功能,我们就需要在Activity转换时对当前数据进行保存. 现在根据以上两种需求,个人提出以下解决方案: 一.锁定Activity运行时屏幕方向,如下图(演示锁定横屏):

Android中Intent组件详解

Intent是不同组件之间相互通讯的纽带,封装了不同组件之间通讯的条件.Intent本身是定义为一个类别(Class),一个Intent对象表达一个目的(Goal)或期望(Expectation),叙述其所期望的服务或动作.与动作有关的数据等.Android则根据此Intent对象之叙述,负责配对,找出相配的组件,然后将 Intent对象传递给所找到的组件,Android的媒婆任务就完成了. 在Google Doc中是这样描述Intent的(摘自Android中文翻译组)当接收到ContentR

Intent应用详解-Android开发

一.Intent介绍: Intent的中文意思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用.Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互.因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关

Intent属性详解二 Action、Category

先看效果图: 1.Action:该activity可以执行的动作 该标识用来说明这个activity可以执行哪些动作,所以当隐式intent传递过来action时,如果跟这里<intent-filter>所列出的任意一个匹配的话,就说明这个activity是可以完成这个intent的意图的,可以将它激活! 常用的Action如下所示: ACTION_CALL activity 启动一个电话. ACTION_EDIT activity 显示用户编辑的数据. ACTION_MAIN activit