目录

Activity

生命周期

任务栈

启动模式

Intent Flag

taskAffinity属性

1.Activity

activity的简单介绍就不写了,作为最常用的四大组件之一,肯定都很熟悉其基本用法了。

2.生命周期

首先,是都很熟悉的一张图,即官方介绍的Activity生命周期图.

Activity生命周期图

情景:打开某个应用的的FirstActivity调用方法如下:

由于之前已经很熟悉了,这里就简单贴一些图。

Paste_Image.png

按下返回键:

Paste_Image.png

重新打开并按下home键:

Paste_Image.png

再重新打开:

Paste_Image.png

在其中打开一个DialogActivity(SecondActivity)

Paste_Image.png

按下返回:

Paste_Image.png

修改SecondAcitvity为普通Activity,依旧是上述操作:

Paste_Image.png

这里强调一下onSaveInstanceState(Bundle outState)方法的调用时机:

当Activity有可能被系统杀掉时调用,注意,一定是被系统杀掉,自己调用finish是不行的。

测试如下:FirstActivity启动SecondActivity:

Paste_Image.png

如果SecondActivity是android:theme="@android:style/Theme.Dialog"那么:

Paste_Image.png

如果FirstActivity启动SecondActivity后自己调用了finish方法:

Paste_Image.png

也就是说,只要一个Activity转为后台,那么就会调用此方法,因为其有可能被系统杀掉,其中存的Bundle对象就是用来存储数据的,这个也就是onCreate方法中Bundle对象参数savedInstanceState的由来。

3.Acitvity任务栈

一个App会包含很多个Activity,多个Activity之间通过intent进行跳转,那么原始的Activity就是使用栈这个数据结构来保存的。

Task

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (theback stack), in the order in which each activity is opened.

即若干个Activity的集合的栈表示一个Task。

当App启动时如果不存在当前App的任务栈就会自动创建一个,默认情况下一个App中的所有Activity都是放在一个Task中的,但是如果指定了特殊的启动模式,那么就会出现同一个App的Activity出现在不同的任务栈中的情况,即会有任务栈中包含来自于不同App的Activity。

4.启动模式

standard

标准模式,在不指定启动模式的情况下都是以此种方式启动的。每次启动都会创建一个新的Activity实例,覆盖在原有的Activity上,原有的Activity入栈。

测试如下:在FirstActivity中启动FirstActivity:

Paste_Image.png

当只有一个FirstActivity时堆栈情况:

Paste_Image.png

当在FirstActivity中启动FirstActivity时堆栈情况:

Paste_Image.png

这就很显然了,任务栈中一共有两个FirstActivity,即表示每次启动FirstActivity都是创建了一个新的实例。

singleTop

此种模式下,Activity在启动时会进行判断,如果当前的App的栈顶的Activity即正在活动的Activity就是将要启动的Activity,那么就不会创建新的实例,直接使用栈顶的实例。

测试,设置FirstActivity为此启动模式,多次点击FirstActivity中的启动FirstActivity的按钮查看堆栈情况:

(其实点击按钮没有启动新Activity的动画就可以看出并没有启动新Activity)

Paste_Image.png

果然,堆栈中只有一个FirstActivity

如果我在FirstActivity中启动了SecondActivity,此时FirstActivity不就不在栈顶了么,此时我再启动FirstActivity会怎样呢?

测试如下:

Paste_Image.png

很好的验证了,只有在栈顶时,才不会创建新实例。

这种启动模式很适用于接收到消息之后进行显示的界面,总不能每次来消息都创建新实例,那一次来个十几条消息岂不是爆炸了。

在此种模式下,在不创建新的实例的时候,会调用onNewIntent()方法。

总结:栈顶的Activity只会有一个实例,在栈顶的情况下重复启动该Activity只会复用该Activity,而不会创建一个新的,除了栈顶的Activity外,其他的和standard类似,每次启动都会被创建一个新的实例。

onNewIntent(Intent intent)方法介绍

官方解释如下:

This is called for activities that set launchMode to "singleTop" in

* their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}

* flag when calling {@link #startActivity}. In either case, when the

* activity is re-launched while at the top of the activity stack instead

* of a new instance of the activity being started, onNewIntent() will be

* called on the existing instance with the Intent that was used to

* re-launch it.

*

*

An activity will always be paused before receiving a new intent, so

* you can count on {@link #onResume} being called after this method.

*

*

Note that {@link #getIntent} still returns the original Intent. You

* can use {@link #setIntent} to update it to this new Intent.

*

* @param intent The new intent that was started for the activity.

大意就是:

对于使用singleTop启动或Intent.FLAG_ACTIVITY_SINGLE_TOP启动的Activity,当该Activity被重复启动(注意一定是re-launched,第一次启动时不会调用)时就会调用此方法。

且调用此方法之前会先暂停Activity也就是先调用onPause方法。

而且,即使是在新的调用产生后此方法被调用,但是通过getIntent方法获取到的依旧是以前的Intent,可以通过setIntent方法设置新的Intent。

方法参数就是新传递的Intent.

singleTask

1.如果是同一个App中启动某个设置了此模式的Activity的话,如果栈中已经存在该Activity的实例,那么就会将该Activity上面的Activity清空,并将此实例放在栈顶。

测试:SecondActivity启动模式设为singleTask,启动三个Activity:

Paste_Image.png

然后在ThirdActivity中启动SecondActivity(注意不是返回,而是启动):

Paste_Image.png

果然,SecondActivity上的ThirdActivity被清掉了

2.如果是其他应用的Activity启动的本应用中此Activity,那么

- 本应用未启动时,在另一个应用的ActivityY中启动SecondActivity:

Paste_Image.png

显然,此时这个SecondActivity是在一个单独的任务栈中的,且是处于前台的,按下返回键,SecondActivity结束,返回到ActivityY。

- 本应用已经启动了,在后台运行,任务栈中是FirstActivity和SecondActivity,在另一个应用的ActivityY中启动此Activity,此时任务栈的状态:

Paste_Image.png

两个任务栈,每个栈中都有两个Activity。

注意,此时如果按下返回键,会出现什么情况呢,到底是返回到ActivityY,还是返回到FirstActivity?

结果如下:

Paste_Image.png

前台Activity竟然变成了FirstActivity!继续按下返回键,就会返回到ActivityY,ActivityX,然后退出。

也就是说,在ActivityY启动了SecondActivity时,连带着SecondActivity的任务栈也被带到了前台。

那么我不禁要问了,如果SecondActivity启动模式是默认的,会不会是此种情况呢?,其实按照我们前面学的,按照分析的话,应该是SecondActivity在ActivityY所在的App所对应的任务栈中创建一个新的实例,跟原本的SecondActivity所在后台任务栈没有一毛钱关系。

- 本应用已经启动了三个Activity,任务栈中是FirstActivity和SecondActivity和ThirdActivity,此时再由ActivityY启动:

那么稍微思考一下就可以肯定运行结果跟上面是完全相同的,因为在跳转到SecondActivity时,其上面的Activity已经被清空了。

singleInstance

这个模式就很好记,以此模式启动的Activity会存放在一个单独的任务栈中,且只会有一个实例。

测试:SecondActivity启动模式设为singleInstance

FirstActivity->SesondActivity->ThirdActivity->SecondActivity->ThirdActivity

结果:

Paste_Image.png

显然,启动了两次ThirdActivity任务栈中就有两个实例,而SecondActivity在另外一个任务栈中,且只有一个。

5.Intent Flag设置启动模式

在使用Intent启动一个Activity时可以设置启动该Activity的启动模式:

这个属性有很多,大致列出几个:

Intent.FLAG_ACTIVITY_NEW_TASK

每个启动的Activity都在一个新的任务栈中

Intent.FLAG_ACTIVITY_SINGLE_TOP

singleTop

Intent.FLAG_ACTIVITY_CLEAR_TOP

singleTask

Intent.FLAG_ACTIVITY_NO_HISTORY

用此种方式启动的Activity,在它启动了其他Activity后,会自动finish.

6.taskAffinity属性

官方文档介绍如下:

The task that the activity has an affinity for. Activities with the same affinity conceptually belong to the same task (to the same "application" from the user's perspective). The affinity of a task is determined by the affinity of its root activity.The affinity determines two things — the task that the activity is re-parented to and the task that will house the activity when it is launched with the FLAG_ACTIVITY_NEW_TASK flag.

By default, all activities in an application have the same affinity. You can set this attribute to group them differently, and even place activities defined in different applications within the same task. To specify that the activity does not have an affinity for any task, set it to an empty string.

If this attribute is not set, the activity inherits the affinity set for the application (see theelement's taskAffinity.

The name of the default affinity for an application is the package name set by theelement.

大意如下:

这个属性表示的是一个Activity对任务栈的亲和度。有相同的affinity的Activity属于同一个Task,即affinity相同的Activity会被加入同一任务栈。一个任务栈的affinity由其affinity值确定或是其根Activity的affinity确定。这个属性决定两件事,①Activity被re-parented时的任务栈,②以FLAG_ACTIVITY_NEW_TASK启动的Activity所在的任务栈。

默认情况下,同一个应用内的所有的Activity都拥有相同的affinity,你可以通过设置这个值来给Activity分组,甚至将不同应用的Activity放在相同的任务栈中。为了表明一个Activity对任何一个任务栈都不具有亲和力,那么将其设为空字符串。

如果这个值没有设置,那么就默认使用application标签下的这个值。

默认的affinity值为manifest标签下设置的包名。

这样看来的话,通俗易懂的讲,就是给每一个任务栈起个名,给每个Activity也起个名,在Activity以singleTask模式启动时,就检查有没有跟此Activity的名相同的任务栈,有的话就将其加入其中。没有的话就按照这个Activity的名创建一个任务栈。

测试:在App1中设置SecondActivity的taskAffinity为“gsq.test”,App2中的ActivityX的taskAffinity也设为“gsq.test”

FirstActivity->SesondActivity->home->ActivityX

任务栈信息如下:

Paste_Image.png

结果很显然了。

测试:在上述基础上,在ActivityX中进行跳转到ActivityY,ActivityY不指定启动模式和taskAffinity。结果如下:

Paste_Image.png

发现ActivityY在gsq.test任务栈中,这是由于其启动模式是Standard,也就是在启动这个Activity的所在的任务任务栈中。

再将ActivityY指定启动模式singleTask:

Paste_Image.png

这样就没问题了,ActivityY在一个新的任务栈中,名称为包名。

这时从ActivityY跳转到SecondActivity,那应该是gsq.test任务栈只有SecondActivity,ActivityX已经没有了。因为其启动模式是singleTask,在启动它时发现已经有一个实例存在,就把它所在的任务栈上面的Activity都清空了并将其置于栈顶。

还有一点需要提一下,在上面,FirstActivity是App1的lunch Activity,但是由于SecondActivity并没有指定MAIN和LAUNCHER过滤器,故在FirstActivity跳转到SecondActivity时,按下home键,再点开App1,回到的是FirstActivity。

大致就先写这么多吧,好像有点长,废话有点多,估计也有错别字,不要太在意~~~

android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈相关推荐

  1. 【Android游戏开发之八】游戏中添加音频-详解MediaPlayer与SoundPoo!并讲解两者的区别和游戏中的用途!...

    为什么80%的码农都做不了架构师?>>>     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigam ...

  2. 【Android游戏开发之八】游戏中添加音频-详解MediaPlayer与SoundPool的利弊以及各个在游戏中的用途!...

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/312.html 游 ...

  3. Android 触摸事件机制(三) View中触摸事件详解

    本文将对View中触摸事件相关的内容进行介绍.重点介绍的是dispatchTouchEvent(), onTouchEvent()这两个API以及OnTouchListener接口. 注意:本文是基于 ...

  4. Android设置中“强行停止”详解

    Android设置中"强行停止"详解 最近工作上遇到了广播接受不到的问题,查看了<Android 开发艺术探索>一书中关于广播的发送和接受的章节(P356-P362). ...

  5. Android中layout过程详解 (结合Android 4.0.4 最新源码)

    上一篇文章Android中mesure过程详解 (结合Android 4.0.4 最新源码)介绍了View树的measure过程,相对与measure过程,本文介绍的layout过程要简单多了,正如l ...

  6. android调webview的方法,Android中的WebView详解

    Android中的WebView详解 WebView详解 基本用法 布局文件配置WebView android:id="@+id/wv_news_detail" android:l ...

  7. Android 中malloc_debug 原理详解

    版本基于:Android R 关联博文: Android 中malloc_debug 使用详解 0. 前言 最近上项目中遇到一个native 可能内存泄漏的问题,曾考虑使用HWASAN,但这个工具是针 ...

  8. Android中mesure过程详解 (结合Android 4.0.4 最新源码)

    如何遍历并绘制View树?之前的文章Android中invalidate() 函数详解(结合Android 4.0.4 最新源码)中提到invalidate()最后会发起一个View树遍历的请求,并通 ...

  9. Android绘图Canvas十八般武器之Shader详解及实战篇(上)

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有java层的,也有jni层深入到Frame ...

最新文章

  1. Java循环读取文件夹下文件
  2. redux常见问题答疑
  3. HDU1257 最少拦截系统(下降自序列个数)
  4. python numpy.ones(shape, dtype=None, order=’C’) empty(shape[, dtype, order]) empty_like(a) 空数组 全1数组
  5. 如何表示数组所有数都不等于一个数_每日算法系列【LeetCode 523】连续的子数组和...
  6. java解析xml的几种方式
  7. Kafka集群在马蜂窝大数据平台的优化与应用扩展
  8. 用MATLAB将矩阵数据写入txt文件中,打开乱码原因
  9. 安卓学习笔记09:常用布局 - 帧式布局
  10. nvl,空时的推断和取值
  11. C#下的Raw Socket编程实现网络封包监视
  12. IDEA设置鼠标滚轮控制缩放大小
  13. 带妹入坑,她该怎样提高自己的编程能力?
  14. 如何用仅用C语言判断编译器的大小端
  15. 深红色LaTeX PPT模板解释说明
  16. 无中介租房搜房工具 V1.0
  17. 幼儿园案例经验迁移_【投石问路】让案例分析成为幼儿教师自我成长的阶梯
  18. 【C】C语言文件(包括:文件各种读写方式)
  19. Codeforces Round #727 (Div. 2) A~D题
  20. 电脑双屏开机后副屏黑屏_电脑两个显示器怎么设置,电脑显示器黑屏

热门文章

  1. mpvue 从零开始 女友的来电 4 flyio
  2. HAS_NO_PRIVILEGE解决方案
  3. mongodump 备份还原
  4. CDH集群异常处理ERROR  Failure due to stall on seeded torrent.、重装时hdfs提示目录已存在、CDH重启不正常
  5. java数组排序源码_Java 数组工具类排序,最大值最小值等
  6. [优先队列][堆] Luogu P4505 组合子逻辑
  7. 2019 DDCTF 部分writeup
  8. K3CLOUD数据权限授权
  9. [bzoj1011] [HNOI2008]遥远的行星
  10. 内置函数之sorted,filter,map