Activity的LaunchMode

Android中提供了四中Activity的启动模式

1. standard
2. singleTop
3. singleTask
4. signleInstance

standard

  • 标准模式,这也是系统的默认模式,每次启动一个Activity都会创建一个新的实例,不管这个实例是否已经存在,Activity执行正常的生命周期方法
  • 一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈
  • 在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中

当我们使用ApplicationContext去启动standard模式的Activity的时候会报错

报错原因:AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.

  • 这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,所以这就有问题了
  • 解决这个问题的方法是为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标志位,这样启动的时候就会为它创建一个新的任务栈
  • 这个时候待启动的Activity实际上是以singleTask模式启动的

singleTop

  • 栈顶复用模式,在这种模式下,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被回调,通过此方法的参数我们可以取出当前请求的信息
  • 需要注意的是,这个Activity的onCreate、onStart方法不会被系统调用,因为它并没有发生改变
  • 如果新Activity的实例已经存在但不是位于栈顶,那么新Activity仍然会重新创建

singleTask

  • 栈内复用模式,这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动该Activity都不会重新创建实例,和singleTop一样,系统也会回调onNewIntent方法
  1. 当一个具有singleTask模式的Activity请求启动后,系统首先会寻找是否存在其想要的任务栈
  2. 如果不存在,就重新创建一个任务栈,然后创建A实例后把A放到栈中
  3. 如果存在,这是要看A是否在栈中有实例存在
    • 如果有A实例,那么系统就会把A调到栈顶并调用它的onNewIntent方法,由于singleTask默认具有clearTop的效果,会导致栈内所有在A上面的Activity全部出栈,这一点比较特殊
    • 如果不存在,就创建A的实例并把A压入栈中
  • 说明:
  • 什么是Activity所需要的任务栈呢?这要从一个参数说起,TaskAffinity,可以翻译为任务相关性
  • 这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
  • 当然我们可以为每个Activity都单独指定TaskAffinity属性,这个属性值必须不能和包名相同,否则就相当于没有指定
  • TaskAffinity属性主要和singleTask启动模式和allowTaskReparenting属性配对使用,在其他情况下没有意义
  • 另外,任务栈分为前台任务栈和后台任务栈,后台任务栈的Activity位于暂停状态,用户可以通过切换将后台任务栈调到前台

注意:taskAffinity属性的值为字符串,且中间必须含有包名分隔符"."

singleTask模式的Activity切换到栈顶会导致在它之上的栈内Activity出栈,这是因为栈的工作模式是“后进先出”,栈内的元素要想回到栈顶,只能将它之前的Activity全部出栈,即CLEAR_TOP效果

TaskAffinity和singleTask配对使用

  • 这个时候,它是具有该模式的Activity的目前任务栈的名字
  • 待启动的Activity会运行在名字和TaskAffinity相同的任务栈中

TaskAffinity和allowTaskReparenting结合使用

  • 当一个应用A启动了应用B的某个Activity后,如果这个Activity的allowTaskReparenting属性为true的话,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中
  • 可以这么理解:由于A启动了C,这时候C只能运行在A的任务栈中,但是C属于B应用,正常情况下它的taskAffinity值肯定不可能和A的任务栈相同,因为包名不同,所以当B启动后,B会创建自己的任务栈,这个时候系统发现C原本想要的任务栈已经被创建了,所以就把C从A的任务栈中转移过来了
  • 这种情况比较复杂,会产生特殊的效果

singleInstance

  • 单实例模式,这是一种加强的singleTask模式,它除了具有singleTask模式的所有特性外,还加强了一点,那就是具有此模式的Activity,只能单独地位于一个任务栈中
  • 换句话说,比如A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了

如何给Activity指定启动模式

  1. 通过AndroidMenifest为Activity指定启动模式
  2. 通过在Intent中设置标志位来为Activity指定启动模式

这两种方式都可以为Activity指定启动模式,但是二者还是有区别的

首先,优先级上,第二种方式的优先级要高于第一种,当两种同时存在时,以第二种方式为准

其次,上述两种方式在限定范围上有所不同,比如,第一种方式无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识,而第二种方式无法为Activity指定singleInstance模式

第一章04-Activity中常用的标志位的更多相关文章

  1. Android开发艺术探索笔记——第一章:Activity的生命周期和启动模式

    Android开发艺术探索笔记--第一章:Activity的生命周期和启动模式 怀着无比崇敬的心情翻开了这本书,路漫漫其修远兮,程序人生,为自己加油! 一.序 作为这本书的第一章,主席还是把Activ ...

  2. 使用Micrisoft.net设计方案 第一章 企业解决方案中构建设计模式

    第一章企业解决方案中构建设计模式 我们知道的系统总是由简单到复杂,而不是直接去设计一个复杂系统.如果直接去设计一个复杂系统,结果最终会导致失败.在设计系统的时候,先设计一个能够正常工作的系统,然后在此 ...

  3. 第8章 Python类中常用的特殊变量和方法目录

    第8章 Python类中常用的特殊变量和方法 第8.1节 Python类的构造方法__init__深入剖析:语法释义 第8.2节 Python类的__init__方法深入剖析:构造方法案例详解 第8. ...

  4. python正则表达式模块re:正则表达式常用字符、常用可选标志位、group与groups、match、search、sub、split,findall、compile、特殊字符转义

    本文内容: 正则表达式常用字符. 常用可选标志位. group与groups. match. search. sub. split findall. compile 特殊字符转义 一些现实例子 首发时 ...

  5. 【翻译习作】 Windows Workflow Foundation程序开发-第一章04

    1.2.3  Windows Workflow运行时 从Windows Workflow的角度看,可以将工作流活动当成是交给一个工作流处理器去执行的一系列指令或操作码.在Windows Workflo ...

  6. windows核心编程---第一章 谈谈windows中的错误处理机制

        我们写的函数会用返回值表示程序执行的正确与否,使用void,就意味着程序一定不会出错.Bool类型标识true时为真,false时为假.其他类型根据需要可以定义成不同意义.       Win ...

  7. 第1章 Java中常用字符串方法总结

    1.1 charAt方法——提取指定字符 1.2 codePointAt方法——提取索引字符代码点 1.3 codePointBefore方法——获取索引前一个字符的代码点 1.4 codePoint ...

  8. 第一章:eclipse 中修改字体大小和编码格式

    eclipse 中修改字体大小的步骤: 1. 在 eclipse 的工具栏中,找到 weindows 下面的 preferences 2. 在 preferences 的 输出 font ,在 Bas ...

  9. 第一章 用HTML5中的结构元素构建网站

    1.当一个容器需要直接定义样式或通过脚本定义行为时,推荐使用div元素而非section元素. 2.section是需要标题的,而nav或aside没有标题也是可以的. 3.html5轮廓工具 htt ...

随机推荐

  1. docer run 、docker attach 与 docker exec的区别

    进入容器的方式有以下三种: 使用ssh登陆进容器 使用nsenter.nsinit等第三方工具 使用Docker本身提供的工具 最佳方案为使用Docker本身提供的工具 docker run:创建和启 ...

  2. ql的python学习之路-day2

    python中所有字符串操作 , )))), ))))#返回50个长度的字符串,不够左边就以0补充,可以用在十六进制补位(不常用)运行结果: My name is qinjiaxi---------- ...

  3. ql的python学习之路-day1

    写在前面的话:万事开头难,算是系统学习python的一个月了吧,总该写点什么来记录一下,之前看老男孩day1的视频没有开通博客,这次给补上,对于学python还是要好好努力,不能半途而废,还是那句老话 ...

  4. 使用vue实现购物车功能

    页面效果图: html代码: <div class="shop-car" id='car'> <div class="count-custom" ...

  5. docker 学习(一)

    1. docker介绍 1)docker的出现 Docker是诞生于2013年,是dotCloud的一个开源项目,基于Google推出的GO语言实现.遵从Apache2.0协议. 2)docker介绍 ...

  6. [原创][开源] SunnyUI.Net 开发日志:ListBox 增加跟随鼠标滑过高亮

    QQ群里,寸目说,ListBox鼠标移动时,当前行需要焦点,我想了想,不难实现啊 不就是在鼠标移动时重绘Item嘛,何况选中的Item已经改了颜色了. 见UIListBox代码: protected ...

  7. SVN创建分支的相关操作

    目的是为了在项目中进行相应的功能操作的时候避免项目的报错还能进行还原 1.在相应的位置创建分支 项目过大的只在 功能的位置 进行创建分支 Angular的src 不要在其下面进行创建分支 他有严格的文 ...

  8. SPL常用函数

    使用SPL_AUTOLOAD_REGISTER装载类 <?php /** * libs/Test.class.php */ class Test { function __construct() ...

  9. WEB常见攻击及防御

    对于一个Web应用来说,可能会面临很多不同的攻击.下面的内容将介绍一些常见的攻击方法,以及面对这些攻击的防御手段. 一.跨站脚本攻击(XSS) 跨站脚本攻击的英文全称是Cross Site Scrip ...

  10. Python-pygame案例小飞机

    import pygame, sys from pygame.locals import * import random '''飞机躲避导弹''' # 玩家 class Player(pygame.s ...