【Android14 ShellTransitions】(四)Transition收集动画参与者

news2024/9/20 18:41:24

在这里插入图片描述

这一节的内容在WMCore中,现在Transition已经走到COLLECTING状态了,并且可以收集动画参与者了。

那么Transition是在什么时候去收集动画参与者?回到我们最初的ActivityStarter.startActivityUnchecked:

在这里插入图片描述

在调用了TransitionController.createAndStartCollecting后,紧接着就是调用了TransitionController.collect。

在这里插入图片描述

这里看到TransitionController里面首先是判断了一下成员变量mCollectingTransition是否为空,如果不为空,才能将传参WindowContainer收集到该Transition中。

接下来我们重点分析Transition.collect,这里感觉不按照代码顺序分析似乎更有条理一点。

1 Transition.collect第1部分

在这里插入图片描述

1)、如果当前Transition的mState小于STATE_COLLECTING,那么就会异常。

2)、如果当前Transition的mState不是STATE_COLLECTING或者STATE_STARTED,那么就会返回。

这里说明了,只有处于STATE_COLLECTING或者STATE_STARTED的Transition才能收集动画参与者,太早或者太晚都不行。

2 Transition.collect第2部分

在这里插入图片描述

首先看这里needSync的逻辑。

如果,当前正在被收集的WindowContainer不是一个WallpaperWindowToken,

或者,当前参与者中不包含该WindowContainer所在的DisplayContent,

并且,该WindowContainer没有被瞬态隐藏(被Recents遮挡),

那么needSync就为true。

needSync为true,那么继续调用BLASTSyncEngine.addToSycnSet方法:

在这里插入图片描述

很简单,根据传入的Transition的ID找到对应的SyncGroup对象,然后继续调用SyncGroup.addToSync方法:

在这里插入图片描述

该方法内容主要是:

1)、如果当前WindowContainer通过getSyncGroup拿到的SyncGroup为空,说明当前WindowContainer还没有绑定一个SyncGroup,那么就将该WindowContainer添加到SyncGroup.mRootMembers中,并且通过WindowContainer.setSyncGroup方法,将WindowContainer的成员变量mSyncGroup设置为当前SyncGroup,完成绑定。

2)、调用WindowContainer.prepareSync方法。

关于这个prepareSync的逻辑,同样在我们之前分析BLASTSyncEngine的那篇文章中也比较系统的介绍过,因此这里简单再回顾一下。

首先是WindowContainer.prepare方法:

在这里插入图片描述

比较简单,调用子WindowContainer的prepareSync方法,然后将自身的mSyncState设置为SYNC_STATE_READY。

mSyncState有三种状态:

在这里插入图片描述

  • SYNC_STATE_NONE,没有参与到一次同步(或Transition)中。
  • SYNC_STATE_WAITING_FOR_DRAW,等待自身绘制完成。
  • SYNC_STATE_READY,当前WindowContainer已经就绪,但是其子容器可能没有就绪。

一般来说,动画都伴随着界面的改变,比如我们从Launcher启动Contacts,Contacts是一个从无到有的过程,那么动画就需要等待Contacts的窗口绘制完成后才能进行。

因此再看重写了prepareSync方法的WindowState.prepareSync方法的内容:

在这里插入图片描述

重点其实就是这一句,将WindowState的mSyncState置为SYNC_STATE_WAITING_FOR_DRAW。

即对于非WindowState的WindowContainer,比如Task,ActivityRecord,它们在界面发生改变的时候是不需要重绘的,因此它们在prepareSync的时候就可以将mState设置为SYNC_STATE_READY。同理,判断一个Task或者一个ActivityRecord是否就绪,看的主要是它里面的WindowState是否就绪了。

而对于WindowState,在界面发生改变的时候,由于要重绘,并且重绘需要时间,因此WindowState在被添加到动画参与者集合的时候,会先被设置为SYNC_STATE_WAITING_FOR_DRAW。等到绘制完成,为该WindowState调用finishDrawing的时候,它的mSyncState会被设置为SYNC_STATE_READY,表示该窗口已经就绪,可以进行动画。

3 Transition.collect第3部分

在这里插入图片描述

接着看Transition的成员变量mParticipants:

在这里插入图片描述

是一个ArraySet类型的成员变量,看方法最后,是将参与当前Transition的WindowContainer添加进来了,那它的作用和SyncGroup的mRootMembers类似。

从第一部分关于needSync的分析看到,向SyncGroup.mRootMembers添加参与者的条件要比向Transition.mParticipants的条件苛刻一点,因为这个区别,这两个参与者集合中的内容可能不是完全相同的。

4 Transition.collect第4部分

在这里插入图片描述

最后我们再来看一下关于ChangeInfo的这部分。

4.1 例子1 —— 新启动ActivityRecord

还以我们之前分析的从Launcher启动Contacts的流程来,那么在这个时间点,只创建了一个ActivityRecord对象,它的Task还没创建,那么通过Transition.getAnimatableParent获取的WindowContainer自然也就是null了,因此标黄的第一段逻辑就不走了,直接看第二段逻辑。

首先看下Transition.mChanges的定义:

在这里插入图片描述

一个包含了WindowContainer和ChangeInfo键值对的map。

这是我们第一次尝试将当前WindowContainer添加到动画参与者中,因此从Transition.mChanges中肯定是没有当前WindowContainer的,因此这里就会根据该WindowContainer创建一个ChangeInfo对象,并且将这两个对象组成的键值对保存到Transition.mChanges中。

ChangeInfo的构造方法为:

在这里插入图片描述

用来保存改变开始前的WindowContainer的一些信息,大概是这样的用法:

1)、在收集阶段,将基于WindowContainer的当前信息创建一个ChangeInfo,ChangeInfo里保存了我们对WindowContainer感兴趣的特定信息。

2)、发生一些改变。

3)、改变完成后,具体是在Transition.onTransactionReady的时候,拿第一步创建ChangeInfo和现在这个时候的WindowContainer的信息进行对比,从而得知当前WindowContainer在这个过程中发生了哪些变化。

4.2 例子2 —— App切换

在第一个例子中,我们看到由于此时是ActivityRecord刚刚创建的时候,因此ActivityRecord的父容器为空,所以这里仅仅为正在收集的这个ActivityRecord创建了一个ChangeInfo的对象。然而更普遍的情况可能是,不仅为当前正在收集的这个WindowContainer创建了ChangeInfo,还可能会创建更多ChangeInfo对象, 即这段逻辑:

在这里插入图片描述

Transition.getAnimatableParent的定义为:

在这里插入图片描述

如果发生了App的切换,比如从Message界面点击Home回到Launcher,那么就会把Message和Launcher的Task收集起来,走到这里时,传参是Task类型的WindowContainer:

1)、首先Task通过getParent获取到父WindowContainer,即TaskDisplayArea。

2)、TaskDisplayArea复写了WindowContainer.canCreateRemoteAnimationTarget方法:

在这里插入图片描述

返回的是true,那么通过Transition.getAnimatableParent返回了TaskDisplayArea。

3)、最终会为TaskDisplayArea创建一个ChangeInfo对象,添加到Transition.mChanges中。

同理为TaskDisplayArea调用Transition.getAnimatableParent方法,获取到的则是DisplayContent,也会为DisplayContent创建一个ChangeInfo对象添加到Transition.mChanges中。

那么除了为Task创建ChangeInfo之外,这里还会为TaskDisplayArea以及DisplayContent创建ChangeInfo,并且加入到Transition.mChanges中。

最后再来对比一下SyncGroup.mRootMembers、Transition.mParticipants以及Transition.mChangs:

1)、Transition.mParticipants,保存的就是正在收集的那个WindowContainer。

2)、SyncGroup.mRootMembers,由于一些条件限制,保存的WindowContainer比Transition.mParticipants要少一点。

3)、Transition.mChangs,不仅保存了正在收集的那个WindowContainer对应的ChangeInfo对象,还可能保存了它的父WindowContainer对应的ChangeInfo对象。

5 其它collect的情况

看下Transition.collect都在哪些地方调用了:

在这里插入图片描述

并且它也会被TransitionController.collect调用,而TransitionController.collect被调用的地方同样也很多:

在这里插入图片描述

场景太多就不一一分析了,其实万变不离其宗,需要在什么节点把WindowContainer收集进来再去调用Transition.collect就行了,就像之前把ActivityRecord添加到openingApps和closingApps那样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python爬虫学习(2)——requests模块

520那天我向心仪的女孩要微信:“女神,能给我你的微信号吗?” 女神:“给我——爬!!!!” 从那天开始,我就决定要学好爬虫,爬到女神微信号!&#xff…

nacos(一) 安装

一 nacos 1.4.7安装 安装 nacos-server nacos官方下载 说明: 下载1.4.7和2.3.2版本,本专栏后续以1.4.7为例进行讲解补充: nacos-server服务端和nacos-client客户端附加: spring 版本、nacos-server、nacos-client版本要适配思考&#xf…

实战项目:飞机坦克大战 —— 面向对象编程之旅

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、项目概览与背景介绍 二、面向对象编程基本概念解析 1. 类与对象 2. 构造函数与属性封…

执法行动高压下,勒索软件攻击仍持续增加

执法行动 最近几年,随着网络犯罪特别是勒索软件犯罪的日益猖獗,勒索软件攻击已经对网络空间安全构成重大威胁。互联网不是法外之地,执法机构也对应加强了执法力度,对全球威胁重大的网络犯罪团伙进行重点打击。对勒索软件团伙所控…

面向对象编程:坦克飞机大战游戏的重构之旅

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、面向对象编程思想入门 坦克对象的定义 属性与行为方法的实现 二、面向过程与面向对象…

利用大语言模型增强网络抓取:一种现代化的方法

本文将探讨大语言模型(LLMs)与网络抓取的集成,以及如何利用LLMs高效地将复杂的HTML转换为结构化的JSON。 作为一名数据工程师,我的职业生涯可以追溯到2016年。那时,我的主要职责是利用自动化工具从不同网站上获取海量数据,这个过…

TiDB学习3:TiKV

目录 1. TiKV架构和作用 2. RocksDB 2.1 写入 2.2 查询 2.3 Column Families列簇 3. 分布式事务 3.1 事务流程 3.2 分布式事务流程 3.3 MVCC 4. Raft与Multi Raft 4.1 Raft日志复制 4.2 Raft Leader选举 5. TiKV- 读写 5.1 数据的写入 5.2 数据的读取ReadIndex …

正邦科技(day1)

1:充电桩工作了两个半小时,已用电量13度电(一般的话是一个小时7度电) 2:火线(红色,棕色),零线(蓝色) 3:充电桩工作了两个半小时&#…

Vue3骨架屏(Skeleton)

效果如下图:在线预览 APIs 参数说明类型默认值必传animated是否展示动画效果booleantruefalsebutton是否使用按钮占位图boolean | SkeletonButtonPropsfalsefalseavatar是否显示头像占位图boolean | SkeletonAvatarPropsfalsefalseinput是否使用输入框占位图boolea…

FPGA之tcp/udp

在调试以太网的过程中,考虑了vivado IP配置(管脚、reset等),SDK中PHY芯片的配置(芯片地址、自适应速率配置等),但是,唯独忽略了tcp/udp协议,所以在ping通之后仍无法连接。 所以现在来学习一下tcp与udp的区别 ---- 为什…

FTP协议——LightFTP安装(Linux)

1、简介 LightFTP是一个轻量级的FTP(File Transfer Protocol,文件传输协议)客户端软件。FTP是一种用于在网络上传输文件的标准协议,允许用户通过TCP/IP网络(如互联网)在计算机之间进行文件传输。 2、步骤…

sqlserver——查询(四)——连接查询

目录 一.连接查询 分类: 内连接: 1. select ... from A,B ; 2. select ..from A,B where ..; 3.select ...,... from A join B on... 4. where 与 join...on 的区别 5. where位置的先后 导语&#xff1…

统计计算四|蒙特卡罗方法(Monte Carlo Method)

系列文章目录 统计计算一|非线性方程的求解 统计计算二|EM算法(Expectation-Maximization Algorithm,期望最大化算法) 统计计算三|Cases for EM 文章目录 系列文章目录一、基本概念(一)估算 π \pi π(二&…

antd(react) ProFormUploadDragger(Upload)上传组件上传图片及省略图模糊展示

antd(react) ProFormUploadDragger(Upload)上传组件上传图片及省略图模糊展示 本文基于reactantdProComponents 需求:图片模糊展示(数据脱敏) 像营业执照、身份证这种,可能用户不希…

信息学奥赛初赛天天练-13-数论-素数的判定

更多资源请关注纽扣编程微信公众号 1 素数 质数又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,就是该数除了1和它本身以外不再有其他的因数;否则称为合数 1 既非素数也非合数 2 是唯一的偶素数。…

全局查询筛选器适用场景 以及各场景示例

EF Core中的全局查询筛选器(Global Query Filters)是一种强大的功能,可以在实体框架的DbContext级别为特定的EntityType设置默认的过滤条件。这些筛选器自动应用于所有涉及到相关实体的LINQ查询中,无论是直接查询还是通过Include或…

深入解读 ChatGPT 的基本原理(个人总结版)

引言 背景 人工智能(AI)技术自20世纪中期诞生以来,经历了多次革新和进步。从最早的图灵测试,到20世纪末的深蓝计算机击败国际象棋冠军,再到21世纪初谷歌AlphaGo击败围棋冠军,AI技术的飞速发展改变了人们的…

4,八种GPIO模式

资料来源:【STM32基础学习】八种GPIO模式总结-云社区-华为云 (huaweicloud.com) 【STM32基础学习】八种GPIO模式总结-云社区-华为云 (huaweicloud.com) 【STM32基础学习】八种GPIO模式总结-云社区-华为云 (huaweicloud.com) 仅作个人自学笔记,如有冒犯&#xf…

STM32Cube系列教程10:STM32CubeIDE工程创建+串口DMA+IDLE+printf重定向+软中断处理串口数据+非阻塞延时任务

文章目录 工程配置配置时钟配置Debug接口配置串口外设配置时钟树生成代码 配置串口重定向printf配置串口,开启IDLE,开启软中断 配置非阻塞延时任务调度函数编写任务调度函数延时任务创建 编译,下载与测试编译下载测试 前两天收到了ST社区的NU…

C数据结构:二叉树

目录 二叉树的数据结构 前序遍历 中序遍历 后序遍历 二叉树的创建 二叉树的销毁 二叉树的节点个数 二叉树叶子节点个数 二叉树第K层节点个数 二叉树的查找 层序遍历 判断二叉树是否为完全二叉树 完整代码 二叉树的数据结构 typedef char BTDataType; typedef str…