在Android应用程序中,可以配置Activity以四种方式来启动,其中最令人迷惑的就是"singleTask"这种方式了,官方文档称以这种方式启动的Activity总是属于一个任务的根Activity。果真如此吗?本文将为你解开Activity的"singleTask"之谜。

在解开这个谜之前,我们先来简单了解一下在Android应用程序中,任务(Task)是个什么样的概念。我们知道,Activity是 Android应用程序的基础组件之一,在应用程序运行时,每一个Activity代表一个用户操作。用户为了完成某个功能而执行的一系列操作就形成了一 个Activity序列,这个序列在Android应用程序中就称之为任务,它是从用户体验的角度出发,把一组相关的Activity组织在一起而抽象出 来的概念。

对初学者来说,在开发Android应用程序时,对任务的概念可能不是那么的直观,一般我们只关注如何实现应用程序中的每一个Activity。事实 上,Android系统中的任务更多的是体现是应用程序运行的时候,因此,它相对于Activity来说是动态存在的,这就是为什么我们在开发时对任务这 个概念不是那么直观的原因。不过,我们在开发Android应用程序时,还是可以配置Activity的任务属性的,即告诉系统,它是要在新的任务中启动 呢,还是在已有的任务中启动,亦或是其它的Activity能不能与它共享同一个任务,具体配置请参考官方文档:

首先在Android源代码工程中创建一个Android应用程序工程,名字就称为Task吧。

关于如何获得Android源代码工程,请参考在 Ubuntu上下载、编译和安装Android最新源代码一文;关于如何在Android源代码工程中创建应用程序工程,请参考在Ubuntu上为 Android系统内置Java应用程序测试Application Frameworks层的硬件服务一文。

这个应用程序工程定义了一个名为shy.luo.task的package,这个例子的源代码主要就是实现在这里 了。

下面,将会逐一介绍这个package里面的文件。

应用程序的默认Activity定义在src/shy/luo/task/MainActivity.java文件中。

它的实现很简单。

当点击它上面的一个按钮的时候,就会启动另外一个名字为“shy.luo.task.subactivity”的Actvity。

名字为“shy.luo.task.subactivity”的Actvity实现在src/shy/luo/task/SubActivity.java文件中:

注意,这里的SubActivity的launchMode属性配置为"singleTask"。

再来看界面配置文件。

它们定义在res/layout目录中,main.xml文件对应MainActivity的界面:

[html] view plaincopy

这样,原材料就准备好了,接下来就要编译了。

有关如何单独编译Android源代码工程的模块,以及如何打包system.img,

请参考如何单独编译Android源代码中的模块一文。

执行以下命令进行编译和打包:

现在,我们如何来确认SubActivity是不是在新的任务中启动并且位于这个新任务的堆栈底部呢?

Android源代码工程为我们准备了adb工具。

可以查看模拟器上系统运行的状况。

执行下面的命令查看:

首先是获得用来启动Activity的Intent的Flags,并且保存在launchFlags变量中。

这里,launcFlags的Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP位没有置位。

因此,notTop为null。

接下来的这个if语句:

这个函数无非就是根据即将要启动的SubActivity的taskAffinity属性值在系统中查找这样的一个Task:Task的affinity 属性值与即将要启动的Activity的taskAffinity属性值一致。

如果存在,就返回这个Task堆栈顶端的Activity回去。

在上面的 AndroidManifest.xml文件中,没有配置MainActivity和SubActivity的taskAffinity属性,于是它们的 taskAffinity属性值就默认为父标签application的taskAffinity属性值,这里,标签application的 taskAffinity也没有配置,于是它们就默认为包名,即"shy.luo.task"。

由于在启动SubActivity之 前,MainActivity已经启动,MainActivity启动的时候,会在一个新的任务里面启动,而这个新的任务的affinity属性就等于它 的第一个Activity的taskAffinity属性值。

这个函数中作用无非就是找到ID等于参数taskId的任务,然后在这个任务中查找是否已经存在即将要启动的Activity的实例。

如果存在,就会把这 个Actvity实例上面直到任务堆栈顶端的Activity通过调用finishActivityLocked函数将它们结束掉。

在这个例子中,就是要 在属性值affinity等于"shy.luo.task"的任务中看看是否存在SubActivity类型的实例,如果有,就把它上面的 Activity都结束掉。

这里,属性值affinity等于"shy.luo.task"的任务只有一个MainActivity,而且它不是 SubActivity的实例,所以这个函数就返回null了。

它是例行性地检查当前任务顶端的Activity,

是否是即将启动的Activity的实例,

如果是否的话,在某些情况下,它什么也不做,就结束这个函数调用了。

这里,当前任务顶端的Activity为MainActivity,它不是SubActivity实例,于是继续往下执行:

到这里,思路就理清了。

虽然SubActivity的launchMode被设置为"singleTask"模式,但是它并不像官方文档描述的一样:

The system creates a new task and instantiates the activity at the root of the new task.

而是在跟它有相同taskAffinity的任务中启动,并且位于这个任务的堆栈顶端,

注意,这里我们设置MainActivity的taskAffinity属性值为"shy.luo.task.main.activity",

设置 SubActivity的taskAffinity属性值为"shy.luo.task.sub.activity"。

重新编译一下程序,在模拟器上把这 个应用程序再次跑起来,

用“adb shell dumpsys activity”命令再来查看一下系统运行的的任务,就会看到:

activity启动模式 android,专题:详解Android组件Activity的启动模式singleTask_51CTO.COM相关推荐

  1. android gridview 详解,Android GridView九宫图

    属性名称 描述 android:columnWidth 设置列的宽度. android:gravity 设置此组件中的内容在组件中的位置.可选的值有:top.bottom.left.right.cen ...

  2. android Fragments详解五:与activity通讯

    与activity通讯 尽管fragment的实现是独立于activity的,可以被用于多个activity,但是每个activity所包含的是同一个fragment的不同的实例. Fragment可 ...

  3. android 目录详解,Android源码目录结构详解

    Android 4.0 |-- Makefile |-- bionic (bionic C库) |-- bootable (启动引导相关代码) |-- build (存放系统编译规则及generic等 ...

  4. android 单例模式详解,android开发设计模式之——单例模式详解

    单例模式是设计模式中最常见也最简单的一种设计模式,保证了在程序中只有一个实例存在并且能全局的访问到.比如在Android实际APP 开发中用到的 账号信息对象管理, 数据库对象(SQLiteOpenH ...

  5. android task详解,Android AsyncTask的使用详解

    当然,我们在进行耗时操作或者更新UI时,是可以使用匿名线程的,但是此种方式是存在缺陷的:第一,线程的开销较大,如果每个任务都要创建一个线程,那么应用 程序的效率要低很多:第二,线程无法管理,匿名线程创 ...

  6. python中打开文件时只允许写入的模式是_详解python中各种文件打开模式

    在python中,总的来说有三种大的模式打开文件,分别是:a, w, r 当以a模式打开时,只能写文件,而且是在文件末尾添加内容. 当以a+模式打开时,可以写文件,也可读文件,可是在读文件的时候,会发 ...

  7. python中文件打开的合法模式组合_详解python中各种文件打开模式

    在python中,总的来说有三种大的模式打开文件,分别是:a, w, r 当以a模式打开时,只能写文件,而且是在文件末尾添加内容. 当以a+模式打开时,可以写文件,也可读文件,可是在读文件的时候,会发 ...

  8. python中以只读形式打开文件的模式是_详解python中各种文件打开模式

    在python中,总的来说有三种大的模式打开文件,分别是:a, w, r 当以a模式打开时,只能写文件,而且是在文件末尾添加内容. 当以a+模式打开时,可以写文件,也可读文件,可是在读文件的时候,会发 ...

  9. 详解 Android 的 Activity 组件

    本文详细介绍了 Android 应用编程中 Activity 的生命周期.通信方式和 Intent Filter 等内容,并提供了一些日常开发中经常用到的关于 Activity 的技巧和方法.通过本文 ...

  10. android打印intent flag,Android flag详解

    Android flag详解 Android flag详解 一.Flag标志位 在阅读源码的时候经常发现有一些标志属性使用一些位操作来判断是否具有该标志,增加标志或者去除标志. 如: 二.addFla ...

最新文章

  1. STL之hashtable源代码剖析
  2. 说说javascprit的基本规范?
  3. Android4.2以及最新SDK的尝鲜使用
  4. 拼多多和国美合作,这可不仅仅是可转债的问题
  5. [转载]Web 研发模式演变
  6. 用qpst修复手机服务器禁用,QPST工具包没有qfil怎么办?
  7. 九宫幻方(蓝桥)深搜
  8. indel该右移还是左移
  9. 2019年大龄程序员书单
  10. Mobile移动5G通信技术详解
  11. 《淘宝店铺营销推广一册通》一1.3 宝贝标题优化
  12. 掌握el-table的formatter方法,提升数据展示效果
  13. innosetup标准安装
  14. 2020中国卓越管理公司颁奖晚宴成功举办,四家香港科大EMBA校友企业获奖
  15. 最火后台管理系统 RuoYi 项目探秘,之二
  16. 最小二乘法拟合椭圆——MATLAB和Qt-C++实现
  17. 什么扫地机器人好用,哪一款扫地机器人好?
  18. 即时通登陆显示服务器失败,即时通服务器地址
  19. Java简单语句项目练习——英雄联盟商城
  20. 一文饱览年度AI盛宴!WAVE SUMMIT+2021峰会精彩回顾

热门文章

  1. 利用python实现Apriori关联规则算法
  2. vue自定义指令v-loading
  3. Elastic Certified Engineer复习记录-复习题详解篇-索引数据(3)
  4. eCalc 一个非常棒的计算器
  5. 无法找到模块“@antv/l7-district”的声明文件。
  6. vim 整行上下移动
  7. Quick thoughts:一种新型、有效的sentence vector模型
  8. 白血病最新研究进展(2022年2月)
  9. JAVA文件的基本操作-------------------------------------破晓
  10. 蓝桥杯 真题 救济金发放、分糖果、刽子手游戏