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

摘要:
堆栈操作:推送和弹出堆栈2.活动Android中的堆栈主要通过活动堆栈进行管理。当活动启动时,系统将根据其配置将其推入特定堆栈,系统处于执行状态。
   在学习Android的过程中,Intent是我们最经常使用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的。
    Intent主要用于2种情景下:(1)发起意图  (2)广播
    它的属性有:ComponentName,action,data,category,extras,flags等,通常情况下,进行Intent的匹配涉及到3个属性:Action,Data,Category。这些东西都须要了解才干对它有个深入的体会。
    以下我就依据最近学习,总结记录下Activity启动模式 及 Intent Flags 与 栈 的关联分析。


文章结构:

1.什么是栈
2.Activity栈
3.Task
4.Activity启动模式
5.Activity栈和Task联系
6.Intent Flags 
7.Activity相关属性taskAffinity

1.什么是栈

栈是一种经常使用的数据结构,栈仅仅同意訪问栈顶的元素,栈就像一个杯子,每次都仅仅能取杯子顶上的东西,而对于栈就仅仅能每次訪问它的栈顶元素,从而能够达到保护栈顶元素下面的其它元素.”先进后出”或”后进先出”就是栈的一大特点,先进栈的元素总是要等到后进栈的元素出栈以后才干出栈.递归就是利用到了系统栈,暂时保存暂时结果,对暂时结果进行保护.

定义栈(Stack)

栈的定义栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。(1)通常称插入、删除的这一端为栈顶(Top),还有一端称为栈底(Bottom)。 (2)当表中没有元素时称为空栈。(3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。栈的改动是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才干删除。

栈的操作:压栈、弹栈

2.Activity中的栈
Android的管理主要是通过Activity栈来进行,当一个Activity启动时,系统会依据其配置将它压入到一个特定的栈中,系统处于执行状态。当用户点击返回或则FINISH()了该Activity,那么它便会被从栈中压出,随之摧毁,依照Activity的生命周期能够知道,假设当前显示的栈中Activity没有被摧毁,那么打开新的Activity时候,会将新打开的压入到栈,原来的依据其显示情况选择状态变化(原Activity依然可见,变为暂停状态(Paused),假设被完毕遮住了,转变为停止状态(Stopped))。
3.Task

Task是与Activity相关的一个重要概念,它密切联系着Activity栈,它简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。(这里仅仅提它和Activity的启动模式来讲)

4.Activity启动模式

属性:android:launchMode  
作用:用于指示Activity怎样启动。
描写叙述:这里有四种模式,与Intent对象中的Activity Flags的属性(FLAG_ACTIVITY_*变量)共同作用,来决定Activity怎样启动来处理Intent。
四种模式
    "standard"  --默认模式
    "singleTop"
    "singleTask"
    "singleInstance"

下面举例说明它们的差别:


standardActivity的默认载入方法,该方法会通过跳转到一个新的activity,同一时候将该实例压入到栈中(无论该activity是否已经存在在Task栈中,都是採用new操作)。比如: 栈中顺序是A B C D ,此时D通过Intent跳转到A,那么栈中结构就变成 A B C D A ,点击返回button的 显示顺序是 D C B A,依次摧毁。


singleTopsingleTop模式下,当前Activity D位于栈顶的时候,假设通过Intent跳转到它本身的Activity (即D),那么不会又一次创建一个新的D实例,所以栈中的结构依然为A B C D,假设跳转到B,那么因为B不处于栈顶,所以会新建一个B实例并压入到栈中,结构就变成了A B C D B。


singleTasksingleTask模式下,Task栈中仅仅能有一个相应Activity的实例。比如:如今栈的结构为:A B C D。此时D通过Intent跳转到B,则栈的结构变成了:A B。当中的C和D被栈弹出销毁了,也就是说位于B之上的实例都被销毁了。


singleInstancesingleInstance模式下,会将打开的Activity压入一个新建的任务栈中。比如:Task栈1中结构为:A B C ,C通过Intent跳转到了D(D的模式为singleInstance),那么则会新建一个Task 栈2,栈1中结构依然为A B C,栈2中结构为D,此时屏幕中显示D,之后D通过Intent跳转到D,栈2中不会压入新的D,所以2个栈中的情况没发生改变。假设D跳转到了C,那么就会依据C相应的launchMode的在栈1中进行相应的操作,C假设为standard,那么D跳转到C,栈1的结构为A B C C ,此时点击返回button,还是在C,栈1的结构变为A B C,而不会回到D。


5.Activity栈和Task联系

Task简单的就是一组以栈的模式聚集在一起的Activity组件集合,类似于一个填充了Activity的容器,最先增加的Activity会处于容器最以下,最后增加的处于容器最上面而从Task中取出Activity是从最顶端先取出,最后取出的是最開始增加Activity,这就是后进先出(Last In First Out)模式,而Activity在Task中的顺序是能够控制的,在Activity跳转时用到Intent Flag能够设置新建activity的创建方式(这里就涉及到了Intent Flag的使用)。

6.Intent Flags 

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

以下列举的是和本文主题相关的Flags属性:

Intent.FLAG_ACTIVITY_NEW_TASK (默认)

默认的跳转类型,它会又一次创建一个新的Activity,只是与这样的情况,比方说Task1中有A,B,C三个Activity,此时在C中启动D的话,假设在AndroidManifest.xml文件里给D加入了Affinity的值和Task中的不一样的话,则会在新标记的Affinity所存在的Task中压入这个Activity。假设是默认的或者指定的Affinity和Task一样的话,就和标准模式一样了启动一个新的Activity.

FLAG_ACTIVITY_SINGLE_TOP

这个FLAG就相当于启动模式中的singletop,比如:原来栈中结构是A B C D,在D中启动D,栈中的情况还是A,B,C,D。

FLAG_ACTIVITY_CLEAR_TOP

这个FLAG就相当于启动模式中的SingleTask,这样的FLAG启动的Activity会把要启动的Activity之上的Activity所有弹出栈空间。比如:原来栈中的结构是A B C D ,从D中跳转到B,栈中的结构就变为了A B了。(这种方法能够用来关闭多个Activity,之后的一篇博文里面会提到)

FLAG_ACTIVITY_BROUGHT_TO_FRONT

这个网上非常多人是这样写的。假设activity在task存在,拿到最顶端,不会启动新的Activity。这个有可能会误导大家! 他这个FLAG事实上是这个意思!比方说我如今有A,在A中启动B,此时在A中Intent中加上这个标记。此时B就是以FLAG_ACTIVITY_BROUGHT_TO_FRONT方式启动,此时在B中再启动C,D(正常启动C,D),假设这个时候在D中再启动B,这个时候最后的栈的情况是 A,C,D,B。假设在A,B,C,D正常启动的话,无论B有没实用FLAG_ACTIVITY_BROUGHT_TO_FRONT启动,此时在D中启动B的话,还是会变成A,C,D,B的。

FLAG_ACTIVITY_NO_USER_ACTION

onUserLeaveHint()作为activity周期的一部分,它在activity由于用户要跳转到别的activity而要退到background时使用。比方,在用户按下Home键,它将被调用。比方有电话进来(不属于用户的选择),它就不会被调用。
那么系统怎样区分让当前activity退到background时使用是用户的选择?

它是依据促使当前activity退到background的那个新启动的Activity的Intent里是否有FLAG_ACTIVITY_NO_USER_ACTION来确定的。

注意:调用finish()使该activity销毁时不会调用该函数

FLAG_ACTIVITY_NO_HISTORY

意思就是说用这个FLAG启动的Activity,一旦退出,它不会存在于栈中,例如说!原来是A,B,C这个时候再C中以这个FLAG启动D的,D再启动E,这个时候栈中情况为A,B,C,E。

7.Activity相关属性taskAffinity

Activity 中的 android:taskAffinity 这个属性介绍:

   Activity为Task拥有的一个affinity。拥有同样的affinity的Activity理论上属于同样的Task(在用户的角度是同样的“应用程序”)。Task的affinity是由它的根Activity决定的。 
   affinity决定两件事情——Activity又一次宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK标志启动的Activity宿主的Task。
    默认情况,一个应用程序中的全部Activity都拥有同样的affinity。捏能够设定这个特性来重组它们,甚至能够把不同应用程序中定义的Activity放置到同样的Task中。为了明白Activity不宿主特定的Task,设定该特性为空的字符串。
    假设这个特性没有设置,Activity将从应用程序的设定那里继承下来(參考<application>元素的taskAffinity特性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。


注:以上的android:taskAffinity仅仅有通过标志位为FLAG_ACTIVITY_NEW_TASK的Intent启动Activity时,该Activity的这个属性才会生效,系统才会将具有同样Task亲和力的Task切换到前台,然后启动该Activity,否则该Activity仍然执行在启动它的Task中。


    上面总结了下Activity启动模式 及 Intent Flags 与 栈 的关联分析,便于之后一篇文章中跳转模式的了解使用。

免责声明:文章转载自《Activity启动模式 及 Intent Flags 与 栈 的关联分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇设置ubantu的软件源地址Docker中的镜像分层技术详解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【Activity、service】点击不同的图片播放不同的声音

      一下,我只把主要的代码贴出来给大家,如果哪里写的不好,希望大家能多多指教,灰常感谢。  /** 定义播放小孩声音的ACTION */ public static String SOUND_ACTION = "com.vtion.ym.box.sound"; XxxActivity.java    Activity里面中的代码 View Cod...

Sqlite-Sqlite3中的数据类型

大多数的数据库引擎(到现在据我们所知的除了sqlite的每个sql数据库引擎)都使用静态的、刚性的类型,使用静态类型,数据的类型就由它的容器决定,这个容器是这个指被存放的特定列。 Sqlite使用一个更一般的动态类型系统,sqlite中,值的数据类型跟值本身相关,而不是与它的容器相关。Sqlite的动态类型系统和其他数据库的更为一般的静态类型系统相兼容,但...

APP漏洞自动化扫描专业评测报告

一、前言 目前在业界有很多自动化检测APP安全性的在线扫描平台。为了了解目前国内移动APP在线漏洞扫描平台的发展情况,我进行了一次移动安全扫描平台的评测分析;主要从漏洞项对比、扫描能力对比以及扫描结果这三个方向来对比。 希望此次的调研结果可以为读者提供更加可靠的安全漏洞扫描服务建议。 二、分析对象 这一章主要介绍需要对比的扫描平台和需要测试的APP样本。...

Android学习笔记八:用Broadcast Receiver跨进程(跨app)通信

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7515194.html 在前面介绍四大组件的时候提到了可以对外部事件进行过滤的Broadcast Receiver,这里就对它的用法作进一步的探讨。 一:Broadcast Receiver的使用 主要有以下三个流程:定义接收器,在其中定义接收到广播后的响应行为——注册...

android 定时器的使用

1、android中通常是使用AlarmManager来定时启动一个单次或重复多次操作的。具体的说就是我们通过AlarmManager设定一个时间和注册一个intent到系统中,然后在该时间到来时,系统为我们发送一个广播,即执行我们设定的Intent(要执行的操作),通常我们使用 PendingIntent来实现“要执行的操作”,PendingIntent...

android中LitePal的使用

网上有一篇文章写的挺好的,推荐给大家:安卓项目实战之:数据库框架 LitePal 3.0 的使用详解 LitePal是对SQLite数据库操作进行了封装,采用对象映射的方式操作SQLite数据库,简化了对SQLiter的操作 我也是使用的是最新的LitePal3.0 1、首先添加依赖,引入LitePal3.0,在build.gradle中添加如下内容: i...