Android Activity launchMode研究

Activity的Launch mode一共有四种:
standard, singleTop, singleTask, singleInstance, 默认情况下是standard.
 

四种启动模式分为两组

Activity的这四种启动模式可以分为两组:
standard和singleTop是一组, 这两种模式标记的activity可以有多个实例(被初始化多次), 这些实例可以属于任何task, 并且可以被放在activity stack中的任何位置. 通常情况下,这两种模式标记的activity会被启动到调用startActivity()的那个task里, 除非Intent对象包含了FLAG_ACTIVITY_NEW_TASK这个标记, 则会启动一个新的task.
singleTask和singleInstance是另一组, 这两种模式的activity只能开始一个task, 它们永远在activity stack的根部, 而且设备在一个时间内只能持有一个activity的实例, 也即只有一个这样的task.
 

launchMode说明

standard

默认模式.
每次有一个新的Intent对象来启动standard activity时, 这个activity的一个新的实例就会被创建,来处理这个intent,也即每一个activity实例处理一个intent.

singleTop

与standard模式类似,一个新的singleTop的activity的实例也可能被创建,来处理一个新的intent.
但是,如果目标task中已经有一个这个singleTop的activity的实例,并且它是在栈顶,则这个已经存在的实例将接受这个新的intent( onNewIntent() 方法被调用), 新的实例不会被创建. 
其他的情况,比如,存在实例在目标task,但是不在栈顶;或者它在一个栈顶,却不在目标task,则新的实例都会被创建,并且放在栈顶, 这时候的行为和standard一样.

singleTask

singleTask和singleInstance唯一的区别就是, singleTask的activity允许其他activity在它的task中.
启动模式为singleTask的activity永远在它的task的根部, 同时, 其他的activities (launch mode为standard和singleTop) 可以被启动到这个task中.
 
系统在启动一个activity的时候,发现它的launchMode是singleTask, 并不能保证就会真的开启一个新的task, 还会检查activity的taskAffinity属性.
如果taskAffinity属性没有指定,默认是application的taskAffinity,名称即包名.
如果发现这个taskAffinity指定的task已经存在,则会在该task中新建一个activity; 如果该task不存在,才会新建一个task.
 
做了一个实验,用一个standard的activity来start一个singleTask的activity:
没有指定taskAffinity时, 它们的taskId相同, 说明它们还是在同一个task里;
为singleTask的activity指定一个新的taskAffinity后,singleTask的activity得到的taskId就和standard的不同了, 说明这时候开启了一个新的task.
 
在启动一个singleTask的activity实例时, 如果系统中已经存在这样一个实例, 将会把这个实例调度到task栈顶, 并清除它的task中栈上方的所有activities.
  

singleInstance

一个launch mode为singleInstance的activity, 不允许其他的activity在它的task中, 它自己是这个task中唯一的activity. 如果它启动另一个activity, 那个新的activity会被分配到一个不同的task中去, 就好像intent中含有FLAG_ACTIVITY_NEW_TASK Flag一样.
 
系统在启动一个activity的时候,如果发现它的launchMode是singleInstance,就会启动一个新的task,因为这种activity不会跟别人共用task. 所以和singleTask不同, singleInstance不需要特殊指定taskAffinity.
在singleInstance中启动的activity也不会跟它放在同一个task里, 根据要启动的activity的taskAffinity选择,可能在其他已有的task里,也可能开启新的task, 总之不是在singleInstance的task里.
 
  

taskAffinity属性

taskAffinity属性规定了activity归属于什么task. 有相同这一属性的activities从概念上来讲, 应该属于同一个task, 从用户的角度来看, 属于同一个应用.
一个task的affinity是由它的根activity的affinity决定的.
 
affinity决定两件事情:
1.activity re-parented到哪个task; 可以查看allowTaskReparenting 属性的说明.
2.当activity被带有FLAG_ACTIVITY_NEW_TASK flag的Intent启动时,哪个task来收容这个activity.
 
默认情况下, 一个application中的所有activities拥有相同的affinity.
你可以设置taskAffinity这个属性来将activities分组,也可以将不用应用中定义的activities放在同一个task里. 也即: 跨应用,跨进程的activities可以在同一个task里.
如果要设定一个activity没有对任何一个task的affinity, 可以将这个属性设为一个空字符串.
 
如果Activity的taskAffinity属性没有被设置, activity会继承application的这个属性. 对于application来说, 默认的affinity的名字就是manifest元素指定的包名.
所以默认情况下, 一个application中的所有activities有着相同的affinity, 名称即应用包名.
 
注意: 自己指定taskAffinity时,需要以应用包名开头,或者是省略包名,用点开头,后面加上一个自己取的名字. 否则会在安装时报错.
 

Up Navigation

在App中,所有非Home的屏都应该提供给用户一种方法,让用户通过点击action bar上的Up键, 来返回到应用逻辑上的prarent screen.
从Android 4.1,即API 16开始,可以通过activity的android:parentActivityName 属性来指定每个activity逻辑上的parent.
通过上面的属性指定了parent之后,就可以通过 NavUtilsAPI来navigate Up到parent了.
 
在这里想说的是, 在navigate up到一个当前stack上的activity时, 具体的行为是由parent activity的launch mode决定的.
如果parent activity是singleTop(或者up intent包含了FLAG_ACTIVITY_CLEAR_TOP Flag), parent activity就会被带到栈顶, 而且它的状态会被保存, Navigation intent被parent的 onNewIntent() 方法所接收.
如果parent activity的launch mode是standard(并且up intent不包含 FLAG_ACTIVITY_CLEAR_TOP Flag), 当前的activity和它的parent都会被弹出栈, 并且parent activity的新实例会被建立,来接收这个intent.
 
 

参考资料:

 
Activity elements:
Tasks and Back Stack:
Providing Up Navigation
 

Android Activity launchMode研究的更多相关文章

  1. android Activity生命周期(设备旋转、数据恢复等)与启动模式

    1.Activity生命周期     接下来将介绍 Android Activity(四大组件之一) 的生命周期, 包含运行.暂停和停止三种状态,onCreate.onStart.onResume.o ...

  2. Android Activity的加载模式和onActivityResult方法之间的冲突

    前言 今天在调试程序时,发现在某一Activity上点击返回键会调用该Activity的onActivityResult()方法.我一开始用log,后来用断点跟踪调试半天,还是百思不得其解.因为之前其 ...

  3. Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();singleTask的两种启动方式。

    原文:Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();singleTask的两种启动方式. Android Activity 的四种启动模 ...

  4. Android自定义View研究--View中的原点坐标和XML中布局自定义View时View触摸原点问题

    这里只做个汇总~.~独一无二 文章出处:http://blog.csdn.net/djy1992/article/details/9715047 Android自定义View研究--View中的原点坐 ...

  5. Android物业动画研究(Property Animation)彻底解决具体解释

     前p=1959">Android物业动画研究(Property Animation)全然解析具体解释上已经基本展示了属性动画的核心使用方法: ObjectAnimator实现动画 ...

  6. Android Activity启动流程源码全解析(1)

    前言 Activity是Android四大组件的老大,我们对它的生命周期方法调用顺序都烂熟于心了,可是这些生命周期方法到底是怎么调用的呢?在启动它的时候会用到startActivty这个方法,但是这个 ...

  7. Android Activity标签属性

    Android Activity标签属性 Activity 是 Android 系统四大应用组件之一,用户可与 Activity 提供的屏幕进行交互,以执行拨打电话.拍摄照片.发送电子邮件等操作开发者 ...

  8. Android Activity全面解析

    Android Activity全面解析 首先,就从Android四大组件Activity开始. 1.Activity生命周期方法完全解析   activity_lifecycle.png 1).on ...

  9. [转]Android Activity的加载模式和onActivityResult方法之间的冲突

    前言 今天在调试程序时,发现在某一Activity上点击返回键会调用该Activity的onActivityResult()方法.我一开始用log,后来用断点跟踪调试半天,还是百思不得其解.因为之前其 ...

随机推荐

  1. 45 个非常有用的 Oracle 查询语句

    ​ 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快 ...

  2. 【记录】JS 获取 URL 中文参数编码

    比如 URL:http://www.xxxx.com/中文参数 这个在 js 获取"中文参数"的时候会出现乱码. 解决方法:decodeURIComponent(获取的中文参数);

  3. ModelState.IsValid总为false原因

    总结在开发中遇到的一个问题 ModelState.IsValid 一直是false 且在局部变量中,没有发现有问题啊,Model非常正常有木有,可是为什么 ModelState.IsValid 总是f ...

  4. java.util.ConcurrentModificationException异常处理

    ConcurrentModificationException异常处理 ConcurrentModificationException异常是Iterator遍历ArrayList或者HashMap数组 ...

  5. Struts2 源码分析——DefaultActionInvocation类的执行action

    本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...

  6. SignalR的Javascript客户端API使用方式整理

    SignalR的服务端提供了两种实现方式,分别是PersistentConnection和Hub,这两种方式的侧重点不同: PersistentConnection更接近于底层,编程接口比较简单,传输 ...

  7. jQuery Mobile案例,最近用Moon.Web和Moon.Orm做了一套系统

      一.简介 先说说,我们的主题.jQuery Mobile,最近用Moon.Web和Moon.Orm做了一套系统 jQuery Mobile是jQuery 在手机上和平板设备上的版本.jQuery ...

  8. cacert.pem

    ## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Wed Sep 14 03:12:05 ...

  9. .NET开源高性能Socket通信中间件Helios介绍及演示

    一:Helios是什么 Helios是一套高性能的Socket通信中间件,使用C#编写.Helios的开发受到Netty的启发,使用非阻塞的事件驱动模型架构来实现高并发高吞吐量.Helios为我们大大 ...

  10. Js apply方法详解

    我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家 ...