Intent中有显示Intent和隐式Intent,显示Intent一般用于程序内部并且明确Activity的名字,启动时一般是intent = new Intent(上下文,Activity名字.class);隐式Intent一般用于不同应用程序的交互。开发中经常用到了显示Intent,而Intent的启动后的Activity会由系统开启Task进行管理,以先进后出的形式进行管理,而且默认的管理方式是每次开启Activity都要进行实例化,那么如果想要改变默认的管理方式,使得其更符合开发的需要,就需要进行某些设置。
下面是我的一些学习笔记:有三个方面,1,Intent Flag部分;2,LaunchMode 部分; 3,Manifest中<activity>属性
一:Intent Flag部分
Intent Flag中只是学习那些可以改变Task管理方式的Flag,这个在官方的文档中有给出详细的介绍http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_BROUGHT_TO_FRONT;
这个标识一般不由程序代码设置,而是当launchMode被设置为singleTask时系统帮你设定的
前提:Activiy A,B,C,D在“FlagTest应用”中
场景演示:在Launcher中单击“FlagTest应用”图标,Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),Activity A 启动 Activity B ,此时Activity B 的launchMode设置为singleTask,Activity B启动Activity C,Activity C启动Activity D(TaskA堆栈的状态为:ABCD),Activity D启动Activity B,因为Activity B的启动模式为singleTask,所以系统会为Activity B 设定 FLAG_ACTIVITY_BROUGHT_TO_FRONT,那么这时的TaskA堆栈的状态为:AB。
如果启动了设置此标识的intent,那么在activity被启动之前,这个标识将会使得与此Activity相关联的任何栈被清空。结果就是,这个activity成为另一个空栈的根activity,而其他老的activity被销毁。这个只能和FLAG_ACTIVITY_NEW_TASK相结合使用。
如果设置了此标识,并且这个Activity已经运行在当前的栈中,那么不是启动此Activity的新实例,而是在此Activity上的其他Activity会被销毁,然后这个intent将会被派发到旧的Activity(此时在栈顶)
前提:Activity A,B,C,D在同个应用中
场景演示:Activity A启动开僻Task堆栈(Task堆栈状态: A),Activity A 启动 Activity B,Activity B 设置了FLAG_ACTIVITY_CLEAR_TOP这个标识,Activity B启动Activity C,Activity C启动Activity D(TaskA堆栈的状态为:ABCD),Activity D启动 Activity B,那么此时C,D则会被销毁,Task堆栈的状态:AB。
如果设置了此标识,这在栈中的Activity标记了一个当栈被重置的时候应该被清除的还原点。就是说,当下次栈携带有FLAG_ACTIVITY_RESET_IF_NEEDED标识回到了前台(这是用户从主界面重启动的典型结果),那个被设置了还原点的Activity和在这个Activity上的Activity将被销毁,并且用户无法返回到他们,但能够返回到这个Activity之前的
这个比较适合有分割点的程序。例如:
场景演示:Activity A启动开辟了Task堆栈(Task堆栈的状态为:A),可能在Activity A在要浏览图片而启动了Activity B来显示图片,此时的Task堆栈状态为:AB,当用户离开了当前的Task后,再从主页面启动该程序,那么显示的就是该图片,这就会让用户困扰,所以就应该在这个Activity B中设置FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,当重新回到此Task的时候,Activity B就会被销毁,此时的Task堆栈状态为:A,那么与用户交互的就是Activity A而不是让用户困扰的图片。
如果设置,新的Activity不会在最近启动的Activity的列表中保存。
如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的Activity。
这个Flag与startActivityForResult(intent, requestCode)的效果一样。
这个标识一般不由程序代码设置,而是当Activity在历史记录中(长按home键)被启动时系统设置的
不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。
在一个新的栈中启动这个Activity,如果你将要启动的Activity已经在一个栈中运行了,那么这个栈将记住它最近的状态然后被放置到前台,而这个Activity中onNewIntent()中接收这个新的intent,这个与launchMode的singleTask有相同的行为。
设置此标识,系统首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的Activity的亲和性一样),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的Activity顺序不变,如果没有,则新建一个栈来存放被启动的Activity
1,前提:Activity A,B,C都在“FlagTest应用“中
场景演示:Activity A启动开辟Task堆栈,状态为:A,接着Activity A启动Activity B ,Activity B启动Activity C,而Activity C设置了FLAG_ACTIVITY_NEW_TASK,默认同个应用中的taskAffinity相同,此时的Task堆栈状态为:ABC.
2,前提:Activity A在”FlagTest应用“中,Activity B,C在”FlagTest应用1“中
场景演示:Activity A启动开辟Task堆栈(TaskA状态为:A),接着Activity A启动Activity B,Activity B设置了FLAG_ACTIVITY_NEW_TASK,这时因为是不同的应用,其taskAffinity不同,则开辟了Task堆栈(TaskB状态为:B),Activity B启动了Activity C,此时TaskB状态为:BC。当从Activity A重新启动Activity B时,因为Activity B已经在TaskB中了,所以是将TaskB返回到前台,而且TaskB中的Activity顺序不变,也就是此时显示给用户的是Activity C。
设置此标识的intent所启动的Activity将没有过渡动画
设置了此标识的intent所启动的Activity将不会放入Task中
场景演示:Activity A启动开辟了TaskA,状态:A,Activity A启动了Activity B,Activity B设置了FLAG_ACTIVITY_NO_HISTORY,当Activity B启动Activity C后,TaskA的状态为AC,因为Activity B不会被放进Task中
这个标识一般与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET一起使用,详细请见上面的 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET。
此标识为栈顶一个Activity只能有一个实例
场景演示:Activity A启动开辟了TaskA,在Activity A中启动Activity B,而Activity B设置了FLAG_ACTIVITY_SINGLE_TOP标识,此时TaskA的状态为:AB,那么当有intnet要请求Activity B时,则不会创建Activity B的实例,而是直接用原来栈中的Activity B,此时TaskA的状态为:AB,如果是默认方式,那么将实例化一个Activity B,那么此时的TaskA状态为:ABB.
这部分Intent Flag是开发中比较常用的Flag,可以通过设定这些Flag达到简易管理项目中的Activity,使其符合项目中Activity跳转的逻辑,当然要进行对项目中全部Activity更有效的管理,还是应该自己实现类似Task的管理功能的。
二:LaunchMode 部分
这部分在官方API guides有详细的介绍http://developer.android.com/guide/topics/manifest/activity-element.html
Activity的启动模式有四种,"standard
", "singleTop
" ,"singleTask
" ,"singleInstance
", 默认的启动模式是standard,这四种模式分为4中,standard,singleTop是一种,Activity能够被实例化多次,这些实例可以属于任何的栈,singleTask,singleInstance是另一中,他们只能开启一个栈,并且总是存在于栈低。
三:Manifest中<activity>属性
这部分在官方的开发者文档中有详细的介绍http://developer.android.com/guide/topics/manifest/activity-element.html;
与Intent有关的部分属性:1,taskAffinity;2,alwaysRetainTaskState; 3,clearTaskOnLaunch; 4,finishOnTaskLaunch
1,taskAffinity属性:
(1) taskAffinity属性应和FLAG_ACTIVITY_NEW_TASK标志及allowTaskReparenting属性结合使用
(2) 与FLAG_ACTIVITY_NEW_TASK标志结合:
a. 前题: Activity A, 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在"FlagTest应用"中, Activity C在"FlagTest1应用"中, 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属性:
场景演示: 在"FlagTest应用"中有Activity A, Activity A与"FlagTest应用"中的其它Activity有默认的关系(taskAffinity属性都没有设置), 并且allowTaskReparenting属性设置为true, 现在存在一个"FlagTest1应用"启动了"FlagTest应用"中的Activity A, 这时Activity A与"FlagTest1应用"中的Activity在同一个Task,命名这个Task堆栈为TaskA, 这时"FlagTest应用"启动, 并且又打开Activity A, 这时Activity A会从TaskA堆栈中转移到"FlagTest应用"所在的堆栈, 即Activity A可以在多个堆栈中来回转移.
2, alwaysRetainTaskState属性:
如果Task堆栈中的Root Activity设置了此属性值为true, 不管出现任何情况, 一直会保留Task栈中Activity的状态.
3, clearTaskOnLaunch属性:
如果Task堆栈中的Root Activity设置了此属性值为true, 只要你一离开这个Task栈, 则系统会马上清理除了Root Activity的全部Activity.
4, finishOnTaskLaunch属性:
如果某Activity设置了finishOnTaskLaunch属性, 只要你一离开这个Task栈, 则系统会马上清除这个Activity,不管这个Activity在堆栈的任何位置.