Activity启动模式 Tasks和Back Stack

http://www.cnblogs.com/mengdd/archive/2013/06/13/3134380.html

Task是用户在进行某项工作时需要与之交互的一系列activities的集合。这些activities按照它们被打开的顺序,被安放在一个堆栈里(back stack)。

  一个activity甚至可以打开其他应用的activity。

  比如你的应用需要发送一个电子邮件,你可以定义一个intent来执行发送动作,intent包含一些必要的数据,然后启动另一个应用中的activity来执行发送邮件的动作,当邮件发送完,又回到你的activity。

  Android会将这两个activity放在同一个task中来保持一致的用户体验。

Activity压栈

  当前的activity启动一个新的activity时,新的activity会被压在back stack的栈顶并且获得焦点。

  前一个activity仍然在栈中,但是stopped。

  当一个activity停止时,系统会保持它的用户交互状态。

  当用户按下Back键,当前activity会出栈(这个activity会被销毁),前一个activity会被恢复,并且它的UI状态也会被恢复。

  当栈中的activities依次弹出,栈空了之后,task就不存在了。

Multitasking:Task在后台

  Task也只是一个有凝聚力的单元,当用户开启一个新的task,或者Home键回到桌面时,task将会变为在后台运行。

  当Task在后台时,其中所有的activity都是停止的,back stack保持不变,这个task只是失去了焦点。

  Task可以回到前台状态,这样用户就可以回到他们离开的现场,即最顶端的activity会resume。

  后台中可以保持多个task,但是系统可能会kill后台的activity用来恢复内存,这样就会导致activity的状态丢失。

保存Activity状态

  当activity停止时(stopped),系统的默认行为是保存它的状态。

  然而,你可以,并且应该使用回调方法主动保留你的状态,以防activity被系统kill而需要重建。

  当系统为了恢复内存而kill掉activity时,activity的状态信息会丢失。

  但是系统仍然知道这个activity在back stack中的位置,当这个activity返回到栈顶时,系统会重建(recreate)它,而不是像之前一样恢复它(resume)。

  所以为了不丢失用户的工作,你需要实现 onSaveInstanceState() 方法来主动地保存数据。

管理Task

  Android系统是这样管理task和back stack的:将activity按照启动的顺序压入堆栈中,如果一个activity被启动多次,会创建它的多个实例,然后将新的实例压入栈中。

  如果你想介入并更改这种默认的行为也可以。

  比如你可能想在你的某一个activity启动时新开启一个task(而不是放在当前task中);

  又或者,当你启动一个activity时,你希望把它的现有实例提到前面来(而不是在栈顶创建一个新的实例);

  或者,你希望在用户离开你的task时清除除了根activity之外的所有activity。

  要做这些事,你可以通过manifest中 <activity>元素的属性,还可以通过设置 startActivity()中传递的intent的flag来完成。

你可以使用的 <activity> 的属性:

以及主要的intent的flag:

定义启动模式

  启动模式允许你定义一个新的activity实例是如何和当前task关联的。

  你可以通过两种方式来定义启动模式:在manifest中定义或者通过用intent的flag。

  这里有两点需要注意:

  1.有些启动模式只能在manifest中定义,也有一些只能通过intent的flag定义。

  2.当一个activity A启动一个activity B时,如果B在它的manifest中定义了启动模式,但是A通过intent要求它用另一种启动模式,以A的要求为主。

使用manifest file定义启动模式

  可以在manifest文件中 <activity>标签下使用 launchMode 属性定义activity和task关联的方式,它规定了activity如何启动并进入一个task。

  注意,在manifest中定义的启动模式可以被启动activity的intent中的flag标明的模式覆盖。

  有下面几种属性值:

"standard" (the default mode)

  默认模式。在当前task中,activity的新实例被创建,并且传递intent给它。一个activity可以被实例化多次,每个实例可以属于不同的task,一个task也可以有多个它的实例。

"singleTop"

  如果当前task的顶部已经有一个这个activity的实例,系统就通过 onNewIntent() 方法向这个实例传递intent,而不是重新建立activity的实例。

  一个activity可以被实例化多次,并且实例可以属于不同的task,一个task也可以有多个它的实例(顶部的activity不是这个activity的实例时,就会重新实例化)。

"singleTask"

  系统将会重新创建一个task并且实例化activity,将其放在task的根部。

  然而,如果这个activity的实例已经在一个单独的task中存在,系统将会调用 onNewIntent() 方法将新的intent传递给这个已经存在的实例,而不是重新创建实例。

  在任一时刻,只能有一个这个activity的实例存在。

"singleInstance"

  和"singleTask"类似,唯一不同的是系统不会在这个activity的实例所在的task中启动任何其他activity。

  这个activity的实例永远是这个task中的唯一一个成员,这个activity启动的任何其他activity都将在另外的task中打开。

返回处理

  不管activity是在一个新的task启动还是当前task启动,返回键永远把用户带到之前的那个activity。

  但是有一种特殊情况:如果你启动一个启动模式为singleTask的activity,如果这个activity在一个后台task存在实例,那么这整个task将会被放到前台,这时候,back stack就会包含这个task中所有的activities,并且它们是放在栈顶。

  如下图:

使用Intent的flag标明启动模式

  通过设置传递给 startActivity()的intent的flag,可以修改要启动的activity和它的task的关联模式。

  可以使用的flags有:

FLAG_ACTIVITY_NEW_TASK

  和之前讨论过的"singleTask"相同,在新的task中启动activity,如果一个你需要的activity的task已经存在,则将它推向前台,恢复其上一个状态,它通过onNewIntent()收到这个新的intent。

FLAG_ACTIVITY_SINGLE_TOP

  和"singleTop"行为相同,如果被启动的activity是当前顶部的activity,则已经存在的实例收到 onNewIntent(),而不是新建实例。

FLAG_ACTIVITY_CLEAR_TOP

  如果被启动的activity已经在当前task运行,不创建它的新实例,而是销毁在它之上的其他所有activities,然后通过 onNewIntent()传递一个新的intent给这个恢复了的activity。

  这个行为在 launchMode 中没有对应的属性值。

  注意,如果activity的启动模式是"standard",它自己也将被移除,然后一个新的实例将被启动。

  这是因为当启动模式是"standard"时,为了接收新的intent必须创建新的实例。

处理affinities

  Affinity指示了activity更倾向于属于哪个task。

  默认情况下,同一个应用的activities倾向于在同一个task中。你可以通过<activity>标签中的 taskAffinity来修改这种行为。

  详细内容请查看:API Guides: Tasks and Back Stack

  http://developer.android.com/guide/components/tasks-and-back-stack.html

清理Back stack

  如果用户离开一个task很久,系统就会清理这个task中的所有activities,除了根activity。当用户返回到这个task,只有根activity会被恢复。

  

  有一些activity的属性,你可以用来改变这一行为:

alwaysRetainTaskState

  如果这个属性在task的根activity中被设置为true,那么上面描述的默认行为不会发生,即便过了很长时间,task仍将会保持所有的activities。

clearTaskOnLaunch

  如果这个属性在task的根activity中被设置为true,每次用户离开这个task,整个task都会被清到只剩根activity。

  这样用户永远只能返回到它最初的状态,即便离开的时间很短。

finishOnTaskLaunch

  这个属性和上一个很像,但是它作用于单个activity,而不是整个task。

  它可以引起任何activity离开,包括根activity。

  当它被设置为true时,这个activity只在当前会话中属于这个task,如果用户离开再返回,它不会再出现。

开启一个task

  你可以通过给activity一个intent filter(action是"android.intent.action.MAIN",category是"android.intent.category.LAUNCHER"),让这个activity是一个task的进入点。

  如下:

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>

  一个这样的intent filter会使得这个activity的icon和label显示在程序启动处,提供了一种方法,使得用户可以启动这个activity,当它启动后,用户也可以通过它来返回到这个task。

  第二个能力是很重要的:用户必须能够离开一个task,然后通过activity launcher返回到它。

  因为这个原因,两个让activity永远实例化一个task的启动模式:"singleTask" 和"singleInstance",应该仅在activity有一个  ACTION_MAIN 和CATEGORY_LAUNCHER filter的时候用它们。

参考资料

  API Guides: Tasks and Back Stack

  http://developer.android.com/guide/components/tasks-and-back-stack.html

  <activity>标签:

  http://developer.android.com/guide/topics/manifest/activity-element.html

  关于启动模式,还可以参见博文:

  http://www.cnblogs.com/fanchangfa/archive/2012/08/25/2657012.html

时间: 2024-11-05 16:31:22

Activity启动模式 Tasks和Back Stack的相关文章

任务栈和Activity启动模式

!!任务栈和Activity启动模式!! https://blog.csdn.net/ws6013480777777/article/details/83829789 https://blog.csdn.net/infsafe/article/details/5666964 https://developer.android.com/guide/components/activities/tasks-and-back-stack 一直觉得官方和网上很多对于启动模式和intent的flag的介绍是

Android中Activity启动模式详解,可以控制程序按home键后进来还会调用一个自己不喜欢的界面

其实这是很简单的一个问题.但是这还是要对android中activity的启动模式有相当的理解才行,当点击home键的时候,懂Android的人都知道,他会把当前activity放到后退栈中, 栈(Stack)又称堆栈,它是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算.人们把此端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,把另一端称为栈底.向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称为出栈或退栈,它是把栈

activity启动模式笔记

activity启动模式的逻辑主要在startActivityUncheckedLocked()函数中,现在来看下这个函数. final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doRe

Activity启动模式 及 Intent Flags 与 栈 的关联分析

   在学习Android的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的.     Intent主要用于2种情景下:(1)发起意图  (2)广播     它的属性有:ComponentName,action,data,category,extras,flags等,通常情况下,进行Intent的匹配涉及到3个属性:Action,Data,Category.这些东西都需要了解才能对它有个深入的

《Android深入透析》之 浅析Activity启动模式

摘要 Activity的启动模式是一个既基础又容易忽视的问题,但是这个问题有个深刻的认识,对程序员写一个稳定高效的Android程序帮助很大,今天,在B哥引导下,我们对Activity启动模式.Intent Flags做了一番很好的探究,可以这么说,如果你不熟悉或了解Activity的启动模式或者Flags怎么用,今后你在实际开发中,绝对会被困扰,回过头来重新学习这一节,举个例子:有人写出的客户端,为什么崩溃了,底下仍然有一个乃至N个该应用的界面,如果你熟读并且准确理解此章,必然不会出此错误.

【转】Activity启动模式 及 Intent Flags 与 栈 的关联分析

http://blog.csdn.net/vipzjyno1/article/details/25463457    在学习Android的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的.     Intent主要用于2种情景下:(1)发起意图  (2)广播     它的属性有:ComponentName,action,data,category,extras,flags等,通常情况下,进行

《深入透析Android》之 浅析Activity启动模式

前言: Activity的启动模式是一个既基础又容易忽视的问题,但是这个问题有个深刻的认识,对程序员写一个稳定高效的Android程序帮助很大,今天,在B哥引导下,我们对Activity启动模式.Intent Flags做了一番很好的探究. 探究历程: ①   什么是栈 ②   Activity栈 ③   Task ④  Activity启动模式 ⑤  Activity栈和Task联系 ⑥  Intent Flags  ⑦  Activity相关属性taskAffinity 1.    什么是栈

【Android基础】Activity启动模式以及Intent Flags 与 栈 的全面解析

Android开发的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制. Intent主要用于2种情景下:发起意图 .广播 其底层实现原理不在此篇文章的讨论范围,以后会陆续更新上的. 下面我就根据近期学习,总结记录下Activity启动模式 及 Intent Flags 与 栈 的关联分析. 1.首先我们先搞清楚什么是栈: 栈是一种常用的数据结构,栈只允许访问栈顶的元素,栈就像一个杯子,每次都只能取杯子顶上的东西,而对于栈就只能每次访问它的栈顶元素,从而可以达到保护栈顶元

深入理解Activity启动模式

今天看到这个,觉得还不错,于是乎收藏下 作者原创连接    共分3篇: 深入理解Activity启动模式(一)–Activity与进程,线程的关系 深入理解Activity启动模式(二)–Activity,回退栈,Task之间的关系 深入理解Activity启动模式(三)–Activity启动模式特点 概述 Android官网介绍Activity的启动模式时比较含糊,介绍Application,Activity,Task,Process,Thread等概念以及它们之间的关系时,也没有说得清楚.大