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模式

Activity的Flags

  • Activity的Flags有很多,这里主要分析一些比较常用的标记位
  • 标记位的作用很多,有的标记位可以设定Activity的启动模式
    • 比如FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_SINGLE_TOP等
  • 还有的标记位可以影响Activity的运行状态
    • 比如FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS等

大部分情况下,我们不需要为Activity指定标记位,因此对于标记位理解即可

在使用标记位的时候,要注意有些标记位是系统内部使用的,应用程序不需要去手动设置这些标记位,以防出现问题

FLAG_ACTIVITY_NEW_TASK

  • 这种标记位的作用是为Activity指定“singleTask”的启动模式,其效果和在XML中指定该启动模式相同

FLAG_ACTIVITY_SINGLE_TOP

  • 这种标记位的作用是为Activity指定“singleTop”的启动模式,其效果和在XML中指定该启动模式相同

FLAG_ACTIVITY_CLEAR_TOP

  • 具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈
  • 这个模式一般需要和FLAG_ACTIVITY_NEW_TASK配合使用,在这种情况下,被启动的Activity的实例如果已经存在,那么系统就会调用它的onNewIntent
  • 如果被启动的Activity采用standard模式启动,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶
  • singleTask启动模式默认就具有此标记位的效果

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

  • 具有这个标记的Activity不会出现在历史Activity的列表中
  • 当某些情况下,我们不希望用户通过历史列表回到我们的Activity的时候这个标记比较有用
  • 它等同于在XML中指定Activity的属性android:excludeFromRecents="true"

第一章03-Activity的启动模式的更多相关文章

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

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

  2. Android开发艺术2之Activity的启动模式

    Activity是Android的四大组件之一,他的重要性毋庸置疑,对于这么重要的一个组件,我们首先要知道这些都是由系统进行管理和回调的,要理解Activity的启动模式,我们首先来了解一下Andro ...

  3. activity的启动模式和栈管理

     在学习Android的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的.     Intent ...

  4. Activity的启动模式--总结

    3. Activity的任务栈Task以及启动模式与Intent的Flag详解? 2,Activity次级页面和主页间来回跳转,防止重复创建Activity实例 1, activity的启动模式: / ...

  5. Activity生命周期,切换,参数传递,bundle(包),值对象,Activity参数返回,Activity的启动模式

    Activity代表手机屏幕的一屏,或是平板电脑中的一个窗口.它是android应用中最重要的组成单元之一,提供了和用户交互的可视化界面.在一个Activity中,可以添加很多组件,这些组件负责具体的 ...

  6. Activity之启动模式

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. Ac ...

  7. 【Android - 组件】之Activity的启动模式

    Activity的启动模式目前有四种:standard.singleTop.singleTask 和 singleInstance. 1.standard standard 是标准模式,也是系统的默认 ...

  8. Android中Activity的启动模式(LaunchMode)和使用场景

    一.为什么需要启动模式在Android开发中,我们都知道,在默认的情况下,如果我们启动的是同一个Activity的话,系统会创建多个实例并把它们一一放入任务栈中.当我们点击返回(back)键,这些Ac ...

  9. 转 Android中Activity的启动模式(LaunchMode)和使用场景

    转载请注明出处:http://blog.csdn.net/sinat_14849739/article/details/78072401本文出自Shawpoo的专栏我的简书:简书 一.为什么需要启动模 ...

  10. 关于activity的启动模式

    在Android中每个界面都是一个Activity ,界面的切换实际上是对不同Activity实例化的过程.而启动模式就决定Activity启动运行方式. 1.设置方式它是在主配置文件中,Activi ...

随机推荐

  1. fastadmin后台:选择视频并允许上传到服务器

    1.在对应方法的视图  “view/class/add.html" 中上传视频部分添加:data-mimetype="video/mp4" 2.在 ”applicatio ...

  2. oracle [精华] 你是否仍迷信rowid分页?

    http://www.itpub.net/thread-1603830-1-1.html

  3. Jmeter基础-下载与安装

    jmeter下载与安装 下载网址:http://jmeter.apache.org/download_jmeter.cgi windows点击下载zip文件 该版本需要JDK1.8及以上版本 免安装, ...

  4. js 滚动条滑动

    toTop() { let top = document.documentElement.scrollTop || document.body.scrollTop; // 实现滚动效果 const t ...

  5. Jumpserver-跳板机的搭建

    Jumpserver堡垒机 一.Jumpserver堡垒机概述-部署Jumpserver运行环境 01 跳板机概述 跳板机就是一台服务器,开发或运维人员在维护过程中首先要统一登录到这台服务器,然后再登 ...

  6. Cypress系列(2)- Cypress 框架的详细介绍

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html Cypress 简介 基于 JavaSc ...

  7. Java 获取IP工具类、Vo类整理记录

    前言 日常开发中,获取ip是常用的功能,本文记录如何在Java中获取本机外网ip.地理位置,访问用户的外网ip.地理位置,以及指定外网ip的地理位置: 代码编写 1.获取访问用户外网ip,我们从访问者 ...

  8. 完美解决报错Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'

    Failed to convert value of type 'java.lang.String' to required type 'java.util.Date' 首先这个错误的意思是 前台页面 ...

  9. python九九乘法表程序代码

    按照c语言的思路来考虑python的,方法很简单,直接运用双重循环即可,本代码为了代码量少采用的是while嵌套双循环. 取两个随机变量 (1)i和j都从1开始(因为表中最小数值为1) (2)i控制第 ...

  10. nginx 搭建图片服务器(windows 下,linux 下原理应该一样)

    作者的心声:很多知道的.用过的东西,不写下来,下次还要百度查询,浪费时间和精力,故本次写下学习笔记,方便下次查阅. 题外话:如有读者通过我这篇博客解决了工作上的难题,可以给个评论,让我一起分享你的喜悦 ...