【Android14 ShellTransitions】(五)启动Transition

在这里插入图片描述

这一节的内容涉及WMCore以及WMShell,主要是启动Transition。

回到ActivityStarter.startActivityUnchecked方法:

在这里插入图片描述

看下最后启动Transition的部分,在ActivityStarter.handleStartResult中:

在这里插入图片描述

只关注我们要关注的部分。

首先是如果这里的局部变量isStarted为true,就说明这个ActivityRecord是新建的,因此调用TransitionController.collectExistenceChange方法:

在这里插入图片描述

将从正在收集的这个Transition的mChanges中找到这个新建的ActivityRecord的ChangeInfo对象,将其成员变量mExistenceChanged置为true,表示这个WindowContainer在本次改变前后的存在性发生了变化,即从无到有(OPEN),或者从有到无(CLOSE)。

再回到ActivityStarter.handleStartResult,根据我们的分析流程,这里传入的newTransition不为空,所以所以这里继续调用的是TransitionController.requestStartTransition方法。

1 WMCore部分 —— TransitionController.requestStartTransition

在这里插入图片描述

从注释可知,该方法用来向Player(WMShell)端创建一个Transition,但是不要启动。

该方法的内容主要为:

1)、创建一个TransitionRequestInfo对象:

在这里插入图片描述

TransitionRequestInfo是继承了Parcelable的类,用来将WMCore端的一些信息进行封装,发送给WMShell端。

比如这里的triggerTask,如果不为空,就包含了那个生命周期变化(start或者finish)导致本次Transition发生的那个Activity对应的Task的信息。

2)、调用成员变量mTransitionPlayer的requestStartTransition方法,先看这个成员变量mTransitionPlayer:

在这里插入图片描述

类型为ITransitionPlayer,它的定义为:

在这里插入图片描述

大概翻译为:

该接口由WMShell实现,用于启动和播放过渡动画。和IWindowOrganizerController一起使用的流程如下:

  1. WMCore启动一个Activity并调用requestStartTransition方法。
  2. 这个TransitionPlayer的实现执行相应操作,然后调用IWindowOrganizerController的startTransition方法,告诉WMCore正式开始(在此之前,WMCore将收集Transition中的所有更改,但不会认为Transition已准备好进行动画)。
  3. 一旦Transition中所有收集的更改都完成绘制,WMCore将调用onTransitionReady方法,在这里委托实际的动画。
  4. 一旦这个TransitionPlayer的实现完成动画,它通过IWindowOrganizerController的finishTransition方法通知WMCore。此时,ITransitionPlayer的责任结束。

ITransitionPlayer接口中包含两个方法:

  • onTransitionReady: 当Transition的所有参与者准备好进行动画时调用。作为对startTransition方法的响应。
  • requestStartTransition: 当WMCore中的某些内容需要播放Transition时调用,例如在新Task中启动Activity时。

该注释已经解释的很清楚了,现在我们已经在WMCore端封装好需要传递的信息了,下一步就是调用ITransitionPlayer.requestStartTransition将这些信息发送到WMShell端,来通知那边创建一个Transition。

2 WMShell部分 —— Transitions.requestStartTransition

从上面ITransitionPlayer的注释我们知道了ITransitionPlayer的实现端在WMShell,具体则是定义在Transitions中的TransitionPlayerImpl类:

在这里插入图片描述

它实现了ITransitionPlayer中定义的两个方法接口,我们先分析requestStartTransition,后面等遇到的时候再分析onTransitionReady。

Transitions.requestStartTransition的内容为:

在这里插入图片描述

1)、创建一个ActiveTransition对象:

在这里插入图片描述

ActiveTransition中有一个IBinder类型的mToken成员,用来保存从WMCore中传来的Transition的token,那么可以认为WMCore端的Transition和WMShell端的ActiveTransition是一个一一对应的关系,这样也有助于理解TransitionController.requestStartTransition的注释:

”Asks the transition player (shell) to start a created but not yet started transition.“

这里要player创建的transition并非Transition,而是ActiveTransition。

ActiveTransition中的其它成员变量也非常重要,不过现在我不打算全部说明,用到的时候再说吧。

2)、调用Transitions.mHandlers中的每一个TransitionHandler的handleRequest方法,来为这个刚刚创建的ActiveTransition找到一个后续走到Transitions.onTransitionReady时,执行动画的Transitions.TransitionHandler对象,并且添加到Transitions.mPendingTransitions中。后续走到Transitions.onTransitionReady的时候,再从Transitions.mPendingTransitions中拿需要执行动画的TransitionHandler对象。

Transitions的mHandlers成员变量是一个TransitionHandler类型的队列:

在这里插入图片描述

TransitionHandler表示可以处理一组过渡动画的接口:

在这里插入图片描述

该接口定义了以下方法:

  • startAnimation: 开始一个过渡动画。如果handleRequest方法返回非空值,则始终调用此方法来处理特定Transition。否则,仅当之前没有其他handler处理Transition时才调用此方法。
  • handleRequest: 可能处理startTransition请求。
  • 等等…
    开机SystemUI进程起来后,就会向Transitions.mHandlers中添加多个TransitionController的子类:

在这里插入图片描述

从名字上也能看出这些TransitionController的子类对应的不同类型的Transition的动画。

3)、当创建了ActiveTransition后,下一步就是决定哪一个TransitionHandler来处理当前Transition,具体说来则是遍历Transitions.mHandlers,按照顺序对每一个TransitionHandler调用handleRequest方法,看哪一个子类可以处理这个Transition,比如我这里打印的log:

在这里插入图片描述

如果找到了这么一个TransitionHandler对象,那么就把它保存在ActiveTransition.mHandler中,后续onTransitionReady流程会用。

4)、调用WIndowOrganizer.startTransition来启动一个已经创建的Transition,这最终会调用到WindowOrganizerController.startTransition,这就又回到WMCore的部分了,下一节再说。

5)、将WMCore传过来的Transition的token赋值给ActiveTransition.mToken。

6)、将这个创建的ActiveTransition对象添加到成员变量mPendingTransitions中:

在这里插入图片描述

成员变量mPendingTransitions是一个ActiveTransition的队列,用来保存那些已经启动,但是还没有就绪的Transition。

后续Transition就绪的时候,即onTransitionReady流程,就会从mPendingTransitions中拿ActiveTransition对象来执行动画。

3 WMCore部分 —— Transition.start

直接看WindowOrganizerController.startTransition:

在这里插入图片描述

从WMCore到WMShell再到WMCore,我们始终传递着IBinder类型的Transition对应的token,因此这里的Transition是不为null的。

因此只需要关注最后调用的Transition.start。

在这里插入图片描述

正式启动Transition,再次之前可以收集参与者,但是直到启动后Transition才会被视为就绪,即使所有的参与者都已经绘制完成。

1)、将Transition的状态置为STATE_STARTED,之前的状态为STATE_COLLECTING。

2)、调用Transition.applyReady。

在这里插入图片描述

继续调用了BLASTSyncEngine.setReady方法:

在这里插入图片描述

最终调用的是SyncGroup.setReady方法:

在这里插入图片描述

重要的其实就那一句,即将SyncGroup的成员变量mReady设置为true,顺便可以调用WindowSurfacePlacer.requestTraversal,看看SyncGroup是否完成,即它里面的所有参与者是否已经准备就绪(绘制完成)。

mReady这个成员变量还是很重要的,只有被设置为true,系统才会去检查这个SyncGroup是否完成。

4 小结

启动Transition这一节的内容还是挺多的,大概总结一下:

1)、在WMCore侧,调用ITransitionPlayer.requestStartTransition切换到WMShell。

2)、在WMShell侧,创建一个Transitions.ActiveTransition对象,为其找到一个后续执行动画的Transitions.TransitionHandler对象,接着将该Transitions.ActiveTransition对象添加到Transitions.mPendingTransitions中,后续动画就绪的时候,就是从Transitions.mPendingTransitions中拿需要play的Transitions.ActiveTransition对象。

3)、回到WMCore侧,得知在WMShell侧创建了和当前Transition一一对应的ActiveTransition后,这个Transition的状态就从STATE_COLLECTING切换为STATE_STARTED,并且相应的SyncGroup的成员变量mReady也被设置为true。

启动Transition的流程再总结的简单一点,就是之前在WMCore这一侧不是创建了一个Transition对象嘛,现在需要在WMShell这一侧创建一个相应的ActiveTransition。一旦这个ActiveTransition创建完成了,WMShell再告知WMCore,WMCore就知道WMShell那边的前序工作已经完成了,那就把Transition标记为STATE_STARTED,SyncGroup标记为ready。后续Transition满足进入下一个阶段的条件了,再看SyncGroup是不是ready了,如果ready了,就说明WMShell那也有一个ActiveTransition了,Transition就可以进入下一个阶段了。

5 从WMShell发起Transition

之前分析的流程是WMCore先创建一个Transition,然后WMShell再创建一个ActiveTransition。

还有一种方式是WMShell先创建ActiveTransition,然后WMCore再创建Transition,即Transitions.startTransition:

在这里插入图片描述

这个方法被很多地方调用,但都在WMShell:

在这里插入图片描述

可以认为这种方式是由WMShell发起了Transition,而我们之前分析的流程是WMCore发起了Transition。并且这里回调IWindowOrganizerController的是startNewTransition,而我们之前分析的流程回调的是startTransition,区别即在于传入的Transition的token是否为null:

在这里插入图片描述

而在WindowOrganizerController.startTransition中,判断传入的Transition为null,就说明流程是从WMShell发起的,才会去创建Transition对象:

在这里插入图片描述

看一下这里调用的TransitionController.startCollectOrQueue方法:

在这里插入图片描述

我们不讨论排队的情况,并且由于Transition流程是从WMShell发起,所以之前也没有创建过SyncGroup,所以这里是直接调用了TransitionController.moveToCollecting,这个我们之前已经分析过了,重点看下这里的OnStartCollect:

在这里插入图片描述

它接受一个boolean的参数,用来表示这个Transition的启动是否被推迟了,比较典型的场景是在某个TransitionA过程中灭屏,因为灭屏而新创建的这个TransitionB的启动会被推迟,需要等待TransitionA完成。TransitionA完成的时候TransitionB会被启动,即OnStartCollect的onCollectStarted方法在TransitionA结束的时候才被调用,而一般来说Transition在创建后很快就会被启动,因此这种场景下我们就可以认为TransitionB的启动其实是被推迟了,传参deferred就给一个true值。这个时候会检查TransitionB是否还需要启动,或者是被中止(如果TransitionA完成的时候屏幕已经被唤醒了),具体在RootWindowContainer.applySleepTokens:

在这里插入图片描述

这里只是大概提一嘴,不过多分析。

另外在我们分析的流程中,OnStartCollect的onCollectStarted方法是被立即调用的,即以下内容会立即执行:

在这里插入图片描述

1)、调用Transition.start,之前分析过不用多说。

2)、调用WindowOrganizerController.applyTransaction,因为Transition是从WMShell发起的,那么WMShell也要引起一些变化才行,不然WMCore这边不知道哪个WindowContainer变化了,哪些WindowContainer要参与动画。要引起变化,靠的就是WindowOrganizerController.applyTransaction,变化的信息则是保存在了WindowContainerTransaction,这方面也不细讲了,之前分析WindowContainerTransaction系列文章的时候有详细分析过。

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

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

相关文章

网络原理-HTTP协议

HTTP协议 HTTP协议全称为超文本传输协议,除了能传输字符串,还能传输图片、视频、音频等。 当我们在访问网页的时候,浏览器会从服务器上下载数据,这些数据都会放在HTTP响应中,然后浏览器再根据这个HTTP响应显示出网页信息。 抓包 抓包工具本质上是一个代理工具,即我们将构造…

STM32H743+USBHID+CubeMX配置

一、环境准备 电脑系统:Windows 10 专业版 20H2 IDE:Keil v5.35、STM32CubeMX v6.5.0 测试硬件:正点原子阿波罗STM32H743 二、测试步骤 1、使用用例工程 配置STM32H743定时器功能-CSDN博客https://blog.csdn.net/horse_2007s/article/d…

HR招聘面试测评,哪些工作岗位需要测评创新能力?

什么是创新能力? 创新能力指在现有的物质基础上,通过某些特定的条件,促成满足未来社会发展的新事物。无论是个人还是国家都需要巨大的创新能力,因为创新是一切发展的根基,离开了创新,所有的发展都是原地踏…

每日复盘-20240527

今日关注: 六日涨幅最大: ------1--------300956--------- 英力股份 五日涨幅最大: ------1--------300956--------- 英力股份 四日涨幅最大: ------1--------301361--------- 众智科技 三日涨幅最大: ------1--------301361--------- 众智科技 二日涨幅最大: ----…

CAS原理技术

CAS原理技术 背景介绍结构体系术语接口原理基础模式1. 首次访问集成CAS Client的应用2. 再次访问集成CAS Client的同一应用3. 访问集成CAS Client的其他应用 代理模式1. 用户在代理服务器上执行身份认证2. 通过代理应用访问其他应用上授权性资源 背景 本文内容大多基于网上其他…

开机必启截图标注类神器Snipaste,基本使用及技巧

目录 一、软件简介二、基本安装三、自启设置四、快捷操作五、使用技巧 一、软件简介 Snipaste 是一款简单高效的截图工具。只需按下 F1 即可截图(可进行自主设置),再按 F3 即可将截图置顶显示(贴图功能)。你还可以将剪…

反射器与联邦实验

要求: 1、AS1存在两个环回, 一个地址为192.168.1.0/24该地址不能在任何协议中宣告AS3存在两个环回, 一个地址为192.168.2.0/24该地址不能在任何协议中宣告 最终要求这两个环回可以互相通讯; AS1的另一个环回为10.1.1.0/24 AS3的另-个环回为10.1.2.0/24 2、整个AS2的…

JMeter 测试单节点与集群的并发异常率

一. JMeter 测试单节点与集群的并发异常率 下载地址:https://jmeter.apache.org/download_jmeter.cgi 单个tomcat测试结果(2000个用户,每个用户访问100次) nginx集群负载均衡tomcat结果(2000个用户,每个用户访问100次)

YOLOV8逐步分解(5)_模型训练初始设置之混合精度训练AMP

yolov8逐步分解(1)--默认参数&超参配置文件加载 yolov8逐步分解(2)_DetectionTrainer类初始化过程 yolov8逐步分解(3)_trainer训练之模型加载_yolov8 加载模型-CSDN博客 YOLOV8逐步分解(4)_模型的构建过程 在上述文章逐步分解(3)和(4&…

【吊打面试官系列】Java高并发篇 - ConcurrentHashMap 的并发度是什么?

大家好,我是锋哥。今天分享关于 【ConcurrentHashMap 的并发度是什么?】面试题,希望对大家有帮助; ConcurrentHashMap 的并发度是什么? ConcurrentHashMap 的并发度就是 segment 的大小,默认为 16, 这意味着最多同时…

Android:将时间戳转换为本地时间格式

一、效果图 图1,中国的时间格式 图2,美国的时间格式 二、StringUtil.kt代码 import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* object StringUtil {fun formatTimestamp(currentTime: Long): String {var sdf Si…

【STM32】检测SD卡是否插入

【STM32】检测SD卡是否插入 开发环境原理图确定引脚的高低电平中断方式检测插入配置引脚打开引脚的中断编写代码显示SD卡信息引脚中断回调函数 实现的效果 开发环境 软件:STM32CubeIDE1.14.1 硬件:立创天空星STM32F407VE;SD卡 原理图 要确…

isscc2024 short course4 In-memory Computing Architectures

新兴的ML加速器方法:内存计算架构 1. 概述 内存计算(In-memory Computing)架构是一种新兴的机器学习加速器方法,通过将计算能力集成到存储器中,以减少数据移动的延迟和能耗,从而提高计算效率和性能。这种方…

服务器软件架构演进

服务器软件架构演进 背景介绍阶段一:单机部署阶段二:应用与数据分离部署阶段三:启用缓存优化阶段四:启用应用服务器集群阶段五:数据库读写分离阶段六:启用反向代理及CDN加速阶段七:启用分布式文…

ComfyUI简单介绍

🍓什么是ComfyUI ComfyUI是一个为Stable Diffusion专门设计的基于节点的图形用户界面,可以通过各种不同的节点快速搭建自己的绘图工作流程。 软件打开之后是长这个样子: 同时软件本身是github上的一个开源项目,开源地址为&#…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第28课-avatar玩家3D形象

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第28课-avatar玩家3D形象 使用dtns.network德塔世界(开源的智体世界引擎),策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界…

零售EDI:Target DVS EDI项目案例

Target塔吉特是美国一家巨型折扣零售百货集团,与全球供应商建立长远深入的合作关系,目前国内越来越多的零售产品供应商计划入驻Target。完成入驻资格审查之后,Target会向供应商提出EDI对接邀请,企业需要根据指示完成供应商EDI信息…

windows 控制面板卸载程序在注册表中位置

计算机\HKEY_LOCAL_MACHINE或者HKEY_CURRENT_USER\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\荐片高清影音 HKEY_CURRENT_USER 控制面板注册表只有当前用户可见 HKEY_LOCAL_MACHINE 控制面板注册表所有用户可见

【STM32踩坑】HAL固件库版本过高导致烧录后无法运行问题

问题引入 目前STM32CUBEMX已经更新到了6.11版本,对应的固件库也一直在更新; 以STM32F1库为例,目前最新的库对应版本为1.8.5 但是我们会发现,如果直接使用1.8.5版本的固件库生成HAL源码后,烧录是可以烧录,但…

leetcode栈和队列的相关题、有效的括号、用队列实现栈、用栈实现队列、设计循环队列等介绍

文章目录 前言一、有效的括号二、用队列实现栈三、 用栈实现队列四、设计循环队列总结 前言 leetcode栈和队列的相关题、有效的括号、用队列实现栈、用栈实现队列、设计循环队列等介绍 一、有效的括号 leetcode有效的括号 // 动态增长的栈 typedef char STDataType; typedef…