Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

任务栈 启动模式 Task Flag launchMode MD


目录

任务栈

Activity的四种启动模式

Activity启动模式有四种,可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大量重复的Activity等问题。

设置Activity的启动模式,只需要在AndroidManifest.xml里对应的activity标签设置android:launchMode属性。

只记住以下内容就够了:

  • standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
  • singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。
  • singleTask:只有一个实例。
    • 如果在同一个应用程序中启动它,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity全部destory掉并调用它的onNewIntent方法。
    • 如果是在别的应用程序中启动它(比如跳转到QQ),则会新建一个task,并在该task中启动这个Activity。
    • 可以使用singleTask来退出整个应用:将主Activity设为SingTask模式,然后在要退出的Activity中跳转到主Activity,然后重写主Activity的onNewIntent函数,并在函数中加上一句finish。
    • 注意:和singleInstance不同的是,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。
  • singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。

基本概念

栈(Stack)是一种常用的数据结构,栈只允许访问栈顶的元素,栈就像一个杯子,每次都只能取杯子顶上的东西,而对于栈就只能每次访问它的栈顶元素,从而可以达到保护栈顶元素以下的其他元素

"先进后出"或"后进先出"就是栈的一大特点,先进入栈的元素总是要等到后进入栈的元素出栈以后才能出栈。

递归就是利用到了系统栈,暂时保存临时结果,对临时结果进行保护.

栈的基本操作:压栈、弹栈

任务栈简单的说就是一组以栈的模式聚集在一起的Activity组件集合,类似于一个填充了Activity的容器,最先加入的Activity会处于容器最下面,最后加入的处于容器最上面,而从Task中取出Activity时是从最顶端先取出,最后取出的是最开始添加Activity,这就是后进先出模式。而Activity在Task中的顺序是可以控制的,在Activity跳转时用Intent Flag可以设置新建activity的创建方式。

Intent中常用的Flag

Flag表示Intent的标志位,常用于Activity的场景中,它和Activity的启动模式有着密切的联系。

下面列举的是和Activity启动模式相关的Flag属性:

  • FLAG_ACTIVITY_NEW_TASK:系统会检查当前所有已创建的Task中是否有该要启动的Activity的Task,若有,则在该Task上【创建】新的Activity;若没有则新建一个Task,并在该新建的Task上创建Activity。
  • FLAG_ACTIVITY_SINGLE_TOP:这个FLAG就相当于启动模式中的singletop,比如说原来栈中情况是ABCD,在D中启动D,栈中的情况还是ABCD
  • FLAG_ACTIVITY_CLEAR_TOP:这个FLAG就相当于启动模式中的SingleTask,这种FLAG启动的Activity会把要启动的Activity之上的Activity全部弹出栈空间。比如:原来栈中的情况是ABCD,这个时候从D中跳转到B,这个时候栈中的情况就是AB了
  • FLAG_ACTIVITY_NO_HISTORY:这个标记顾名思义意思就是说,用这个FLAG启动的Activity,一旦【不可见】,他就不会存在于任务栈中。比如,原来是ABC,这个时候在C中以这个FLAG启动D的 ,D再启动E,这个时候栈中情况为ABCE。
  • FLAG_ACTIVITY_BROUGHT_TO_FRONT:比方说我现在在A中启动B,启动B时在Intent中加上这个标记,此时在B中再正常启动CD,此时栈的情况是ABCD。如果这个时候在D中再启动B,这个时候栈的情况是 ACDB。
  • FLAG_ACTIVITY_REORDER_TO_FRONT:如果在A,B,C,D正常启动的话,不管B有没有用FLAG_ACTIVITY_BROUGHT_TO_FRONT启动,此时在D中启动B的话,还是会变成A,C,D,B的。
  • FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:这个不知道具体怎么用
  • FLAG_ACTIVITY_NO_USER_ACTION:onUserLeaveHint()是activity周期的一部分,它在activity因为用户要跳转到别的activity而使当前activity要退到background时调用。比如,在用户按下Home键(用户的选择)时,它将被调用;但如果是有电话进来(不属于用户的选择,是系统行为),它就不会被调用。那么系统如何区分让当前activity退到background时使用是用户的choice?它是根据促使当前activity退到background的那个新启动的Activity的Intent里是否有FLAG_ACTIVITY_NO_USER_ACTION来确定的。注意:通过调用finish()使该activity销毁时不会调用该函数

taskAffinity属性

清单文件中,activity 的属性android:allowTaskReparenting用于设定:Activity是否能够从启动它的任务栈中【转移到】另一个与启动它的任务栈有相同taskAffinity属性值的任务栈中,转移时机是在另一个任务栈被带到前台的时候。如果设置为true,则能够转移,如果设置了false,则这个Activity必须要保留在启动它的那个任务栈中。

实验

1、新建两个工程,App1和App2

App1和App2都设置android:taskAffinity="aaa.aaa" android:allowTaskReparenting="true"

先运行App1,然后点击home键,让App1运行在后台

再运行App2,会发现这时显示的是App1的mainActivity,并且长按home键,会发现运行过的程序只有App1。

2、紧接着又在此基础上做了另外一个实验

在App1上新建一个secondActivity,设置android:taskAffinity="aaa.bbb" android:allowTaskReparenting="true"

在mainActivity中startActivity时,设置Intent中flag属性为FLAG_ACTIVITY_NEW_TASK。

然后运行App1,点击进入secondActivity,这时长按home键,会发现运行过的程序中有两个App1,并且一个显示的是mainActivity另一个显示的是secondActivity。

这时点击home键,让程序回到后台

然后运行App2,会发现这时显示的是App1的mainActivity,此时点击返回会直接返回home。

注意,虽然此时App1的mainActivity被finish了,但App1的secondActivity还在后台等着呢。

同样,长按home键,会发现运行过的程序只有App1的两个任务栈,并没有App2。

3、在此基础上对App1再次修改

在App1上新建一个thirdActivity,设置属性android:taskAffinity="aaa.aaa" android:allowTaskReparenting="true"

并在secondActivity中startActivity时,设置Intent中flag属性为FLAG_ACTIVITY_NEW_TASK;

运行App1,点击进入secondActivity,再进入thirdActivity,此时长按home键,会发现运行过的程序中有两个App1,并且一个显示的是secondActivity另一个显示的是thirdActivity。

此时点击返回,会回到mainActivity,再点击返回,会回到secondActivity,再点击返回,回到home页面。

以上实验中,如果startActivity时不设置Intent中flag属性为FLAG_ACTIVITY_NEW_TASK,则若先启动的是App1,那么不管是App1中的Activity还是App2中的mainActivity,都是运行App1的一个任务栈中。

任务栈简单了解

我们在开发项目的过程中,一般都需要在本应用中多个Activity组件之间的跳转,也可能需要在本应用中打开其它应用的可复用的Activity。如我们可能需要跳转到原来某个Activity实例,此时我们更希望这个Activity可以被重用而不是创建一个新的 Activity,但根据Android系统的默认行为,确实每次都会为我们创建一个新的Activity并添加到Task中,这样android系统是不是很傻?还有一点就是在我们每开启一次页面加入到任务栈Task中后,一个Activity的数据和信息状态都将会被保留,这样会造成数据冗余, 重复数据太多, 最终还可能导致内存溢出的问题(OOM)。

  • android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
  • 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
  • 在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
  • 需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。

android系统提供了一套Activity的启动模式来修改系统Activity的默认启动行为。目前启动模式有四种,接下来我们将分别介绍这四种模式。

Standard 模式

又称为标准模式,也是系统的默认模式(可以不指定),在这样模式下,每启动一个Activity都会重新创建一个Activity的新实例,并且将其加入任务栈中,而且完全不会去考虑这个实例是否已存在。

在standard模式下启动三次MainActivity后,都会生成了不同的新实例,并添加到同一个任务栈中。这个时候Activity的onCreate、onStart、onResume方法都会被调用。

singleTop 模式

又称栈顶复用模式,顾名思义,在这种模式下,如果有新的Activity已经存在任务栈的栈顶,那么此Activity就不会被重新创建新实例,而是复用已存在任务栈栈顶的Activity。这里重点是位于栈顶,才会被复用,如果新的Activity的实例已存在但没有位于栈顶,那么新的Activity仍然会被重建。需要注意的是,Activity的onNewIntent方法会被调用。

这种模式通常比较适用于接收到消息后显示的界面,如qq接收到消息后弹出Activity界面,如果一次来10条消息,总不能一次弹10个Activity吧?再比如新闻客户端收到了100个推送,你每次点一下推送他都会进入某个activiy界面(显示新闻只用一个activity,只是内容不同而已),这时也比较适合使用singleTop模式。

singleTask 模式

又称为栈内复用模式。这是一种单例模式,与singTop点类似,只不过singTop是检测栈顶元素是否为需要启动的Activity,而singTask则是检测整个栈中是否存在当前需要启动的Activity,如果存在就直接将该Activity置于栈顶,并将该Activity以上的Activity都从任务栈中移出销毁,同时也会回调onNewIntent方法

singleTask 模式比较适合应用的主界面activity,里面有好多fragment,一般不会被销毁,它可以跳转其它的activity界面再回主架构界面,此时其他Activity就销毁了。当然singTask还有一些比较特殊的场景这个我们后面会一一通过情景代码分析。

singleInstance 模式

在singleInstance模式下,该Activity在整个android系统内存中有且只有一个实例,而且该实例单独尊享一个Task。换句话说,A应用需要启动的 MainActivity 是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A单独在这个新的任务栈中,如果此时B应用也要激活MainActivity,由于栈内复用的特性,则不会重新创建,而是两个应用共享一个Activity的实例。

2019-2-27

任务栈 启动模式 Task Flag launchMode MD的更多相关文章

  1. 任务栈 启动模式 Flag taskAffinity

    关于任务栈Task 栈的概念 栈(Stack)是一种常用的数据结构,栈只允许访问栈顶的元素,栈就像一个杯子,每次都只能取杯子顶上的东西,而对于栈就只能每次访问它的栈顶元素,从而可以达到保护栈顶元素以下 ...

  2. Activity四种启动模式与Flag及affinity属性详解

    Activity有四种加载模式:standard(默认).singleTop.singleTask.singleInstance standard:Activity的默认加载模式,即使某个Activi ...

  3. android Activity的启动模式与flag的见解

    最近做一个安卓项目,想要实现的效果就是:当打开一个按钮的时候,启动了一个A功能,当用户返回到桌面再继续进去的时候,不过之前在哪个Activity,都会先跳转到A功能的那个界面,当用户点击返回的时候,再 ...

  4. Activity的启动模式与flag详解

    Activity有四种加载模式:standard(默认), singleTop, singleTask和 singleInstance.以下逐一举例说明他们的区别: standard:Activity ...

  5. Activity生命周期以及启动模式对生命周期的影响

    前天用户体验反馈的一个需求,要求每次进入应用都定位到首页;这个操作很明显不适合放在首页Activity(启动模式为SingleTask)的onResume中,如果对Activity的启动模式和生命周期 ...

  6. Activity的生命周期和启动模式

    Activity的生命周期分析 典型情况下的生命周期.是指在用户参与的情况下,Activity所经过的生命周期的改变. 异常情况下的生命周期.是指Activity被系统回收或者由于当前设备的Confi ...

  7. Android_Activity的生命周期、跳转方式及参数传递、启动模式。

    Activity的生命周期: onCreat ,onStart,onResume,onPause,onRestart,onStop,onDestroy Activity之间的跳转分为显式跳转和隐式跳转 ...

  8. Activity的任务栈Task以及启动模式与Intent的Flag详解

    什么是任务栈(Task) 官方文档是这么解释的 任务是指在执行特定作业时与用户交互的一系列 Activity. 这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中. 其实就是以栈的 ...

  9. 四大组件之Activity Task任务栈4种启动模式

    1.启动模式 standard,创建一个新的Activity. singleTop,栈顶不是该类型的Activity,创建一个新的Activity.否则,onNewIntent. singleTask ...

随机推荐

  1. Python 中的面向对象和异常处理

    在之前我们已经说过了 Python 中内置的主要的几种对象类型,(数,字符串,列表,元组和字典).而面向对象的核心人物还没出场呢 .那么我们常说的对象是什么类型的呢,其实他的类型就是“类”.继承封装和 ...

  2. 大数据技术之_13_Azkaban学习_Azkaban(阿兹卡班)介绍 + Azkaban 安装部署 + Azkaban 实战

    一 概述1.1 为什么需要工作流调度系统1.2 常见工作流调度系统1.3 各种调度工具特性对比1.4 Azkaban 与 Oozie 对比二 Azkaban(阿兹卡班) 介绍三 Azkaban 安装部 ...

  3. Python csv模块的使用

    1.csv简介 CSV (Comma Separated Values),即逗号分隔值(也称字符分隔值,因为分隔符可以不是逗号),是一种常用的文本 格式,用以存储表格数据,包括数字或者字符.很多程序在 ...

  4. Cpp下匿名对象探究

    先来看看一段代码: #include "iostream" using namespace std; class ABCD { public: ABCD(int a, int b, ...

  5. 出现报错: module build failed error couldn't find preset es2015 relative to directory

    当用webpack 进行 build 的时候, 会出现如上标题的错误, 解决方式是在 上级 或者 上上级目录,删除 .babelrc 文件

  6. Power OJ 2605 SPFA+dp思想

    题目链接[https://www.oj.swust.edu.cn/problem/show/2605] 题意:给出包含N(N <= 5000)个点M条边的有向图,然后求1 - N在满足距离小于T ...

  7. Questions(Updating)

    有时候做题时会遇到一些未学习的零碎知识点,或存疑的疑惑 为防止遗忘,在此记录 1.复数除法与线性变换的关系 Accepted Codeforces 8D(2018.5.9) Definition: 复 ...

  8. 命令神器:lsof 常用

    lsof -i 显示所有网络连接lsof -i 6 获取IPv6信息lsof -itcp 显示tcp连接lsof -i:80 显示指定端口信息lsof -i@172.12.5.6 显示指定ip连接ls ...

  9. PHPExcel 导出2003和2007的excel文档实例

    require_once 'common/excel/PHPExcel.php'; require_once 'common/excel/phpExcel/Writer/Excel2007.php'; ...

  10. 通过Roslyn构建自己的C#脚本(更新版)

    之前写过文章介绍过如何通过Roslyn构建自己的C#脚本,但那篇文章是参考自Roslyn CTP版的,记得本来想等到Roslyn正式版出来重新更新一下文档的,不过记得后来Roslyn是跳票了的,Scr ...