Activity任务栈和启动模式

通过前面的学习,Activity的基本使用都已掌握,接下来一起来学习更高级的一些内容。

Android采用任务栈(Task)的方式来管理Activity的实例。当启动一个应用时,Android就会为之创建一个任务桟。先启动的Activity压在栈底,后启动的Activity放在找顶,通过启动模式可以控制Activity在任务栈中的加载情况。本节将针对Activity的任务栈和启动模式进行详细的讲解。

一、Activity任务栈

在开发Android应用时,经常会涉及一些消耗大量系统内存的情况,例如视频播放、大量图片或者程序中开启多个Activity没有及时关闭等,会导致程序出现错误。为了避免这种问题,Google提供了一套完整的机制让开发人员控制 Android中的任务栈。

Android系统中的任务栈,类似于一个容器,用于管理所有的Activity实例。在存放Activity时,满足“先进后出 (First-In/Last-Out )"的原则。接下来通过一个图例来说明任务找中如何存放Activity,如下图所示。

从上图可以看出,先加入任务栈中的Activity会处于容器下面,后加入的处于容器上面,而从任务栈中取出Activity 出的是最底端的Activity。

但是使用任务栈有以下缺点:

  • 每开启一次页面都会在任务栈中添加一个Activity,而只有任务栈中的Activity全部清除出栈时,任务栈被销毁,程序才会退出。这样就造成了用户体验差, 需要点击多次返回才可以把程序退出。
  • 每开启一次页面都会在任务栈中添加一个Activity还会造成数据冗余, 重复数据太多, 会导致内存溢出的问题(OOM)。

为了解决任务栈产生的问题,Android为Activity设计了启动模式,那么下面的内容将介绍Android中Activity的启动模式。

二、Activity启动模式

在实际开发中,应根据特定的需求为每个Activity指定恰当的启动模式。Activity的启动模式有4种,分别是standard、singleTop、singleTask和singlelnstance。在AndroidManifest.xml中,通过<activity>标签的android:launchMode属性可以设置启动模式。下面针对这4种启动模式。下面针对这4种启动模式分别进行详细的讲解。

01standard模式

standard是Activity默认的启动模式,在不指定Activity启动模式的情况下,所有Activity 使用的都是standard模式。因此,前面使用的Activity都是standard启动模式。

在standard模式下,每当启动一个新的Activity,它就会进入任务栈,并处于栈顶的位置,对于使用standard模式的Activity,系统不会判断该Activity在栈中是否存在,每次启动都会创建一个新的实例。

接下来通过一个图例展示standard模式下Activity在栈中的存放情况,如下图 所示。

从上图中可以看出,在standard 启动模式下Activity01最先进栈,其次是Activity02,最后是 Activity03;出栈时,Activity03最先出栈,其次是Activity02,最后是Activity01,满足“先进后出”的原则。

02singleTop模式

singleTop模式与standard类似,不同的是,当启动的Activity已经位于栈顶时,则直接使用它不创建新的实例。如果启动的Activity没有位于栈顶时,则创建一个新的实例位于栈顶。

接下来通过一个图例展示singleTop模式下Activity在栈中的存放情况,如下图所示。

从上图中可以看出,当前栈顶中的元素是 Activity03,如果再次启动的界面还是Activity03,则复用当前找顶的Activity实例,如果再次启动的界面没有位于栈顶,则会重新创建一个实例。

03singleTask模式

如果希望Activity在整个应用程序中只存在 一个实例,可以使用singleTask模式,当Activity 的启动模式指定为singleTask,每次启动该Activity时,系统首先会检查栈中是否存在该活动的实例,如果发现已经存在则直接使用该实例, 并将当前Activity之上的所有Activity出栈,如果没有发现则创建一个新的实例。

接下来通过一个图例展示singleTask模式Activity在找中的存放情况,如下图所示 。

从上图可以看出,当再次启动Activity02时,并没有新创建实例,而是将Activity03实例移除,复用Activity02实例,这就是singleTask模式,让某个Activity在当前栈中只存在一个实例。

04singleInstance模式

在程序开发中,如果需要Activity在整个系统中都只有一个实例,这时就需要用到singlelnstance模式。不同于上述三种模式,指定为singlelnstance模式的Activity会启动新的任务栈来管理这个Activity。

singlelnstance模式加载Activity时,无论从哪个任务栈中启动该Activity,只会创建一个Activity实例,并且会使用一个全新的任务栈来装载该Activity实例。采用这种模式启动Activity 会分为以下两种情况:

第一种:如果要启动的Activity不存在,系统会先创建一个新的任务栈,再创建该 Activity的实例,并把该Activity加入栈顶,如下图所示。

第二种:如果要启动的Activity已经存在,无论位于哪个应用程序或者哪个任务钱中,系统都会把该Activity所在的任务栈转到前台,从而使该Activity显示出来。

至此,Activity的4种启动模式已经讲解完成,在实际开发中需要根据实际情况来选择合适的启动模式。

三、Activity栈其他配置

在实际开发中除了配置上述的android:launchMode属性来设置启动模式,还常会配置以下属性:

  • android:taskAffinity
  • android:allowTaskReparenting
  • android:clearTaskOnLaunch
  • android:alwaysRetainTaskState
  • android:finishOnTaskLaunch

接下来通过两方面来学习这5个属性。

01Affinity

默认情况下,一个应用程序中的所有Activity都有一个Affinity,这让它们属于同一个Task。当然,每个Activity也可以通过 <activity>中的android:taskAffinity属性设置单独的Affinity。 不同应用程序中的Activity可以共享同一个Affinity,同一个应用程序中的不同Activity 也可以设置成不同的Affinity。 Affinity属性在以下2种情况下起作用:

  1. 当启动 Activity的Intent对象包含FLAG_ACTIVITY_NEW_TASK标记时,系统会为需要启动的Activity寻找与当前Activity不同Task。如果要启动的 Activity的Affinity属性与当前所有的Task的Affinity属性都不相同,系统会新建一个带那个Affinity属性的Task,并将要启动的Activity压到新建的Task栈中;否则将Activity压入那个Affinity属性相同的栈中。
  2. 如果一个Activity的android:allowTaskReparenting属性为true, 那么它可以从一个Task(Task1)移到另外一个有相同Affinity的Task(Task2)中(Task2带到前台时)。 如果一个.apk文件从用户角度来看包含了多个"应用程序",你可能需要对那些 Activity赋不同的Affinity值。

02清空栈

当用户长时间离开Task(当前Task被转移到后台)时,系统会清除Task中栈底Activity外的所有Activity 。这样,当用户返回到Task时,只留下那个Task最初始的Activity了。我们可以通过修改下面这些属性来改变这种行为:

  • android:alwaysRetainTaskState: 如果栈底Activity的这个属性被设置为true,上述的情况就不会发生。 Task中的所有Activity将被长时间保存。
  • android:clearTaskOnLaunch:如果栈底Activity的这个属性被设置为true,一旦用户离开Task, 则 Task栈中的Activity将被清空到只剩下栈底Activity。这种情况刚好与 android:alwaysRetainTaskState相反。即使用户只是短暂地离开,Task也会返回到初始状态 (只剩下栈底Acitivty)。
  • android:finishOnTaskLaunch 与android:clearTaskOnLaunch相似,但它只对单独的Activity操 作,而不是整个Task。它可以结束任何Activity,包括栈底的Activity。 当它设置为true时,当前的Activity只在当前会话期间作为Task的一部分存在, 当用户退出Activity再返回时,它将不存在。

本期的内容较深,不是很好懂,如果不能完全理解先知道就行,等后期有一定经验后再来研究。

原文发布于微信公众号 - 分享达人秀(ShareExpert)

原文发表时间:2017-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏指尖下的Android

菜鸡的MVP架构漫谈

相信大家在网上看过关于MVP架构的博客数不胜数,至于MVP到底是什么,也不需要我再从百度百科复制一遍了,通俗的说MVP就是解决Model和View的耦合,没有使...

10020
来自专栏java一日一条

Android Activity的生命周期和启动模式详解

当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause()->onStop()->onDestory()三个方法。

11410
来自专栏Android干货

Fragment问题集

36070
来自专栏Android机动车

Dagger2系列——实例解析

这篇文章会分享一下实际应用中的Dagger2如何使用,以及Dagger2通过apt插件如何给我们生成代码,以及生成的代码之间的关联。

10420
来自专栏mukekeheart的iOS之旅

Android基础总结(2)——活动Activity

1、什么是活动(Activity)   活动(Activity)是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零个或多个活动,但不...

33890
来自专栏程序员互动联盟

【专业技术】Android内存泄漏简介

存在问题: 不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露。 解决方案: 其实如果我们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它...

30130
来自专栏向治洪

android orm持久层框架

android数据库开发   Android中内置了sqlite,但是常用的开发语言java是面向对象的,而数据库是关系型的,二者之间的转化每次都很麻烦(主...

19250
来自专栏漏斗社区

天空飘来五字:Android逆向smali

本期,我们将继续Android逆向动态分析之smali篇。内容包括smali语言介绍与动态调试。

13320
来自专栏james大数据架构

android防止内存溢出浅析

Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M。但是Android采用的是Java语言编写,所以在很大程度上,Android的内存...

19250
来自专栏学海无涯

Android开发之Retrofit小试牛刀

感觉好久没有写Android的文章了,囧囧囧!因为Retrofit实在是太火了, 火得我一直跃跃欲试,但是由于种种原因吧,一直都没有用过。周末闲来无事,利用一个...

29390

扫码关注云+社区

领取腾讯云代金券