Activity启动模式总结

news/2024/11/15 8:24:39/

前言

相关文章其实很多了。通过对阅读调试相关源码后,我认为还是有必要按自己的理解梳理总结输出。

核心源码在com.android.server.wm.ActivityStarter#startActivityInner

启动方式详解

Standard

默认模式,会直接在打开的Task上创建。不管taskAffinity

在不同Task中打开同一个Activity,Activity会被创建多个实例,分别放进每一个对应的Task。

SingleTop

与Standard相似,唯一的区别就是。

如果task顶部已经是该Activity,就不会创建新的,而是复用顶部Activity并通过onNewIntent传输Intent给复用的Activity。

SingleTask(ATMS会添加FLAG_ACTIVITY_NEW_TASK)

启动的时候会在Activity的taskAfinity对应的task启动(task名称是第一个activity的taskAfinity)。

如果该task已经存在该activity,就将该activity上面的activity都退出,并将intent传到onNewIntent。并将该task启动到前台(叠在当前的task上)

隐式添加FLAG_NEW_TASK

SingleInstance(ATMS会添加FLAG_ACTIVITY_NEW_TASK)

与SingleTask类似,但是会创建并独占一个task(名字与taskAfinity一致)。

这个时候会有两个相同(taskAfinity一样)的task,当再次启动这个Activity时,不会重建,只会调用onNewIntent。并把该Task移动到前台。由于最近任务只能显示不同的taskAfinity的task,所以,这个时候去启动另外一个标准启动模式的OtherActivity会把OtherActivity的task切换到前台,并在OtherActivity对应的task上创建Activity,该Task与SingleInstance的那个Activity所在的Task同名(taskAffinitiy一样)。这个时候如果切换到最近任务列表(SingleInstance的那个Task会切到后台)再回来,点击返回按钮会发现SingleInstance的Activity不见了,包括在最近任务列表也不见了

computeLaunchingTaskFlags

    private void computeLaunchingTaskFlags() {......if (mInTask == null) {if (mSourceRecord == null) {// This activity is not being started from another...  in this// case we -always- start a new task.if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {Slog.w(TAG, "startActivity called from non-Activity context; forcing " +"Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;}} else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {// The original activity who is starting us is running as a single// instance...  this new activity it is starting must go on its// own task.mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;} else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {// The activity being started is a single instance...  it always// gets launched into its own task.mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;//自动添加上FLAG_ACTIVITY_NEW_TASK}}}

特殊配置

allowTaskReparenting(FLAG_ALLOW_TASK_REPARENTING)

默认情况下,Activity只会归属于一个Task,如果设置allowTaskReparenting=true,这样activity可以在task之间切换。比如你A应用启动B应用的B Activity(只设置了allowTaskReparenting=true),那么B Activity就直接在A应用当前task上启动(到这里类似Standard的效果,但是在Android 9 10 有问题),然后这个时候打开B应用,A应用的B Activity就会移动到B的task上显示(到这里类似SingleTask)

FLAG分析

FLAG_ACTIVITY_NEW_TASK

从源码来看,Intent.FLAG_ACTIVITY_NEW_TASK是启动模式中最关键的一个Flag,依据该Flag启动模式可以分成两类,设置了该属性的与未设置该属性的:

  1. 对于非Activity启动的Activity(比如Service或者通知中启动的Activity)需要显示的设置Intent.FLAG_ACTIVITY_NEW_TASK
  2. singleTask及singleInstance在AMS中被预处理后,隐形的设置了Intent.FLAG_ACTIVITY_NEW_TASK
  3. 启动模式是standard及singletTop的Activity不会被设置Intent.FLAG_ACTIVITY_NEW_TASK,除非通过显示的intent setFlag进行设置。

Intent.FLAG_ACTIVITY_NEW_TASK的作用是在启动Activity时,ATMS会根据taskAffinity查找对应的Task,并将Activity添加到该Task中,然后启动

如果不添加该Flag,就直接在发起请求的Task上启动目标Activity,否则就在目标Activity所对应的TaskAffinity的task中启动。由于Service没有对应的Task,所以通过Service启动Activity就必须要添加Intent.FLAG_ACTIVITY_NEW_TASK才行。

以Service启动的Activity为例。

  Intent intent = new Intent(BackGroundService.this, A.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);    

FLAG_ACTIVITY_CLEAR_TASK

必须配合FLAG_ACTIVITY_NEW_TASK一起使用。

当设置了FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK。如果目标task已经存在,将清空已存在的目标Task,否则,新建一个Task栈,之后,新建一个Activity作为根Activity。Intent.FLAG_ACTIVITY_CLEAR_TASK的优先级最高,基本可以无视所有的配置,包括启动模式及Intent Flag,哪怕是singleInstance也会被finish,并重建。

FLAG_ACTIVITY_CLEAR_TOP

清空源Activity所在Task中已存在的目标Activity之上的Activity,包括目标Activity也会被清空,然后重建目标Activity。

当与FLAG_ACTIVITY_SINGLE_TOP一起使用时,则不会清空目标Activity,而是重用(调用onNewIntent)

当与FLAG_ACTIVITY_NEW_TASK一起使用时,清空的task是目标Activity的taskAffinity对应的task,一直到目标Activity为止,不包含目标Activity

FLAG_ACTIVITY_SINGLE_TOP

单独使用,与SingleTop效果一样。

当与FLAG_ACTIVITY_CLEAR_TOP一起使用时,核心作用就是保证在清空源Activity所在Task顶部Activity的时候不会清空已存在的目标Activity,而是重用目标Activity,也就是调用onNewIntent

当与FLAG_ACTIVITY_NEW_TASK一起使用时,清空的Task是目标Activity的taskAffinity对应的task。

FLAG_ACTIVITY_MULTIPLE_TASK

这个标识用来创建一个新的task栈,并且在里面启动新的activity(所有情况,不管系统中存在不存在该activity实例),经常和FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK一起使用。这上面两种使用场景下,如果没有带上FLAG_ACTIVITY_MULTIPLE_TASK标识,他们都会使系统搜索存在的task栈,去寻找匹配intent的一个activity,如果没有找到就会去新建一个task栈;但是当和FLAG_ACTIVITY_MULTIPLE_TASK一起使用的时候,这两种场景都会跳过搜索这步操作无条件的创建一个新的task。和FLAG_ACTIVITY_NEW_TASK一起使用需要注意,尽量不要使用该组合除非你完成了自己的顶部应用启动器,他们的组合使用会禁用已经存在的task栈回到前台。

源码分析清空Activity的逻辑

重建目标Activity的条件是:标准启动模式,并且没有FLAG_ACTIVITY_SINGLE_TOP,就是重建目标Activity,否则就只是调用onNewIntent

    private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);if (r == null) return null;final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,PooledLambda.__(ActivityRecord.class), r);forAllActivities(f);//这个方法主要是清空r(要启动的目标Activity)之上的Activityf.recycle();// Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we// will finish the current instance of the activity so a new fresh one can be started.if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE //标准启动模式&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0 //不是SIGLE_TOP&& !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {//满足上面的条件就清空目标Activity,否则就调用onNewItentif (!r.finishing) {r.finishIfPossible("clear-task-top", false /* oomAdj */);return null;}}return r;}

http://www.ppmy.cn/news/49015.html

相关文章

使用PCL滤波器实现点云裁剪

主要目的就是根据已知的ROI区域,对点云进行裁剪。要么留下点云ROI区域,要么去除。 ROI区域一般都是一个矩形,即(x,y,width,height)。 那么封装的函数形式一般如下: pcl:…

有始有终的编码原则

基本情况 在程序员的修炼之道之中,说到: 这个建议能简单地应用到大多数场合。简单说就是,分配资源的函 数或对象,对释放资源应负有责任。 这其实就是我们常说的谁分配的就谁负责释放,这也是内存释放的一个原则&#x…

18、定制化原理

文章目录 1、定制化的常见方式2、原理分析套路 【尚硅谷】SpringBoot2零基础入门教程-讲师:雷丰阳 笔记 路还在继续,梦还在期许 1、定制化的常见方式 ● 修改配置文件; ● xxxxxCustomizer; ● 编写自定义的配置类 xxxConfigurat…

ROS学习第二十九节——URDF之joint

此处留疑问,link,joint的origin子标签到底是怎么样的一种位置关系??? https://download.csdn.net/download/qq_45685327/87717336 urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的…

WIFI-OmniPeek抓包

一、简介 有时候,我们需要抓取空口数据包来分析数据,此时就需要了解抓包软件如何使用。此时需要准备如下东西: SNIFFER:AC-12000 软件:OmniPeek 二:抓包 打开OmniPeek,新建捕获。 确认设备是否…

面试华为,花了2个月才上岸,真的难呀····

花2个月时间面试一家公司,你们觉得值吗? 背景介绍 美本计算机专业,代码能力一般,之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发,第二份实习由于大三暑假回国的时间比…

华为,找寻科技秋天里的春光

捷克导演伏拉基米尔米切尔在2001年指导了一部电影,叫做《秋天里的春光 Bab lto》。 我很喜欢这个名字,它吐露着一种简单质朴的美好。回望历史,我们会发现文明与知识经常陷入秋天,但却因为人类的一次次努力,最终我们迎来…

Pandas 练习, 常见功能查阅

Pandas 安装 pandas 库: conda install pandas数据 git clone https://github.com/KeithGalli/pandas.git练习 import pandas as pddata_dir "/data_dir"df pd.read_csv(f{data_dir}/pandas/pokemon_data.csv) df.shape(800, 12)df.head()#NameType 1Type 2HPA…