老生常谈 activity 启动模式

最近新参加的项目中使用到了activity
的 singleInstance
模式并在开发中产生了一些bug,发现组内的同事们对launchmode这件事情还缺少一些基本的认识。给大家讲解的同时还是觉得可以把这个过程记录下来,尽管是基础部分很古老的知识但是很多开发者也还是没有认真的学习过,即使已经熟悉了仔细想想也还会有些收获的。一些基本概念的清晰理解在日常的开发也都有着意想不到的重要性。下面开始老生常谈。

在AndroidMenifest.xml中每一个activity的launchMode可以有4种选项:standard,singleTop,singleTask,singleInstance。它们之间有很多区别,也有一些启程转接的东西。

standard,也是系统默认的方式。

每一次调用,系统都会创建一个新的activity然后他被置于当前发起intent的activity所在的task中的顶部。形式上可以这样描述:

新开启的#1 activity会统一位于当前task顶部与用户交互,如果此时用户关闭当前页面按钮会回到#0 activity。

在实际代码的运行中我们可验证这个过程,请看下面的dumpsys activity主要信息截图:

同一个app中intent调用的发起方和响应方同处于一个task中,他们的先后关系也如前面图示中描述的样子。

同一个app中的调用场景是最常见的,那如果进行跨app的调用场景下又是个什么样子呢?请看下面dumpsys activity的主要信息截图:

请注意红色线框中的信息,两个activity分属不同的app中,通过intent的调用被排进了同一个task中与前面同一个app中是一致的,因此对于back按钮的响应也与前述是一致的。

这里面请注意ProcessRecord的信息与前面的截图有着截然的区别,不同的ProcessRecord ID表明了2个activity分别运行于2个不同的process中。这里确认了另一个重要的信息,android中task和process两者间并没有必然的关联性。这样设计也为夸app的信息传送添加了一种方式。

下一个是 singleTop

它的基本操作过程与standart是一致的。关键的区别在于如果被调用的activity在task的顶部,那么系统会继续使用它并调用onNewIntent传入新的intent信息。此时需要特别关注的是新的intent在调用onNewIntent后并不会自动与activity关联,使用者必须自己调用setIntent()来建立这种关系。

这个过程图示说明如下:

对于back按钮的响应和面前的standard是一致的,这里就不重复描述了。

在2次调用中dumpsys activity的主要信息是一致的,如下截图:

singleTask

google的文档中是这样说明的“The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to
existing instance through a call to its onNewIntent() method, rather than creating a new one.”

相对于前面的类型这一个就比较复杂了,我们分几步来详细说明。

首先:第一次调用这个activity时,系统会将他单独放入一个task中,然后将新的task切换到前台与用户交互。当用户关闭当前页面,系统会将前台被调用的activity移出task,并将启动他的task切换到前台。这个过程如下图所示:

与singleTop相似的是,一旦activity被启动后续所有的调用都会传递到到这个实例上,并将它所处的task切换到前台,而不会开启新的实例。同时也有者显著的区别,在task中如果activity没有处于顶部那么调用的时候它前面的activity都会被清除掉,以保证它位于顶部。如下图所示:

通过分析描述为可以知道系统中这个activity只会被启动一次,常驻于他启动时所在的task并保持为根节点。

以上都是对文档的理解,下面用实际的代码检验一下理解的是否正确。

首先我们在app2中创建如下activity描述:

然后进行跨越app的调用,从app1中通过intent调用这个activity,这时dumpsys
activity的主要信息截图如下:

这里可以清楚的看到系统在intent调用后创建了task#4527在其中安置了新启动的MainActivity2,同时新建的task处于前台与用户交互状态。对back的响应也一如我们预期的那样。

我们再验证同一个app中调用的场景。操作步骤为启动app2然后调用这个activity。此时dumpsys
activity的主要信息截图如下:

这时候可以看到并没有创建新的task,启动的activity也没有被放到所处task的底部,此处系统的行为开始与文档中描述的不符。再来尝试跨越app的调用,启动app1调用MainActivity2,此时dumpsys
activity的主要信息截图如下:

在这个截图中我们发现了与文档描述相似的地方,app1中发出的调用启动的是前面已经打开过的activity,同时依然被放置于原先的task并没有被加入app1的task。

接下来继续验证activity处于task下部时,被调用的场景。首先通过已经被启动的MainActivity2调用其它activity,此时dumpsys
activity的主要信息截图如下:

然后从activity#1上调用MainActivity2,此时dumpsys
activity的主要信息截图如下:

系统将activity#1从task中移除,activity#0被置于task顶部与用户进行交互。在此处终于与文档中描述的完全一致了。

singleInstance

和前面的 “singleTask”
非常相似的作用,他们的区别主要有2个:第一被调用的activity一定会独处于一个task中;第二这个activity会是task中唯一的一个activity。这个过程如下图所示:

与 “singleTask”和 “singleInstance”相关的还有另外一个参数“taskAffinity”,它的存在对它们的行为有着很重要的影响。我们来看下它的效果。

首先从activity配置开始:

然后在同一个app中启动MainActivity2,看一下dump sys activity的截图信息:

这里看到的信息和前面是完全一致的。但是设备中的截图是这样的:

`

这样的情况大多数同学都会很意外吧,同一个app,同一个ProcessRecord ID,在系统的任务管理里面却被列为2个单项?而且这两个单项都是可以独立关闭的。

在前面已经说明了,系统中process和task是分开管理的并没有必然的联系。在这里我们更进一步可以发现系统的任务管理是基于task的而非基于process,当我们在手机上通过系统的任务管理器关闭一个项目的时候,实际上系统关闭的是一个task,而并不是直接作用于一个process。这样的情况可能和大部分人心中的认知是不符的。关于系统对task和process管理将会在后面的文章里介绍。

特别说明一下,文章里的测试结果~截图~dump信息都是在google官方的模拟器和原生的5.0系统中获取的,其他第三方系统或多或少在行为和显示上都会有一些区别,具体机型还需要具体测试。

在这次的介绍里面我最想表达给读者的是3个关键点:

第一:关于学习,务必主要基于官方的文档和说明。在我自己学习的过程中验证过很多网络上文章中的内容,可以发现其中有很多错误的信息,也有很多文章几经转载与原文已经有很大的出入了。

第二:学习的过程中务必要加入自己的实践操作,将各种相关的工具结合起来验证,前面的检验中已经发现了即使官方的文档中也可能有一些不是很精确的内容。特别是对于android这样的开源系统,经过各个厂商的定制它们的产品在一些细节的地方系统行为也是各有不同的,没有经过实际的验证很可能会发现一些意外的情况。

第三:细节。所有的学习务必要关注细节,对细节的关注不足很可能导致在认知上与实际情况产生偏差。

心心相念,必有回响。

时间: 2024-08-04 00:04:32

老生常谈 activity 启动模式的相关文章

深入Activity,Activity启动模式LaunchMode完全解析

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53221384 本文出自[DylanAndroid的博客] 深入Activity,Activity启动模式LaunchMode完全解析 在平时的开发中,我们可能会了解到Activity的任务栈还有Activity的启动模式.那么Activity的启动模式都分别是怎么样的呢?如果设置了这些启动模式对任务栈有事么影响 ,还有就是这么启动模式在实际的开发中有什么应用呢?这里用图例和d

Android中Activity启动模式详解,可以控制程序按home键后进来还会调用一个自己不喜欢的界面

其实这是很简单的一个问题.但是这还是要对android中activity的启动模式有相当的理解才行,当点击home键的时候,懂Android的人都知道,他会把当前activity放到后退栈中, 栈(Stack)又称堆栈,它是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算.人们把此端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,把另一端称为栈底.向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称为出栈或退栈,它是把栈

activity启动模式之singleTop

activity启动模式之singleTop 一.简介 二.设置方法 在AndroidManifest.xml中将要设置为singleTop启动模式的页面进行配置 <activity android:name="activityLaunchSingleTop.ActivityB2" android:launchMode="singleTop"></activity> 三.代码实例 效果图: 代码: activityLaunchSingleTo

Activity启动模式

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. Android总Activity的启动模式分为四种: Activity启动模式设置: <activity android:name=".MainActivity" android:launchMode="standard" /> Activity的四种启动模式:

activity启动模式笔记

activity启动模式的逻辑主要在startActivityUncheckedLocked()函数中,现在来看下这个函数. final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doRe

Android Activity启动模式

在Android的联机文档中,有对Activity的简单介绍,现在通过编写代码对Activity的启动模式做一个深入的理解.在配置文件AndroidManifest.xml中,activity元素的android:launchMode属性用来配置对应Activity的启动模式,目前有以下四种启动模式:1.standard2.singleTop3.singleTask4.singleInstance如果不对Activity设置启动模式,默认就是standard模式 一.standard 请看以下代

Activity启动模式的深入分析

网上关于Activity启动模式的文章非常多,但是看起来都千篇一律,看完之后我们都能理解这4种启动模式,不过官方api对singleTask这个启动模式解释有些争议,导致我其实并没有真正理解这几种模式,特别是对实际开发到底怎么用还是一知半解,于是花了一天时间好好研究这4种启动模式. 首当其冲应该知道Task的概念,它是我们一系列操作连贯跳转activity形成的一个activity栈,后进先出也就是说当前看到的activity在最上面,关于Task的概念老罗一篇博客说的比较清楚,引自老罗博客:

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

   在学习Android的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的.     Intent主要用于2种情景下:(1)发起意图  (2)广播     它的属性有:ComponentName,action,data,category,extras,flags等,通常情况下,进行Intent的匹配涉及到3个属性:Action,Data,Category.这些东西都需要了解才能对它有个深入的

activity启动模式之standard

activity启动模式之standard 一.简介 就像一只叠加在栈中 如果退出,就一个个退出,其实就是我们自己用手机的那种感受 二.代码实例 activityLaunchStandard.MainActivity 1 package activityLaunchStandard; 2 3 4 5 6 import com.example.activityLaunchStandard.R; 7 8 import android.app.Activity; 9 import android.co