View工作原理分析1 - 初识ViewRoot和 DecorView

简介: 以下相关资料均来自 Android艺术探索,部分内容加入了一些我个人的理解。

ViewRoot和DecorView相关分析

ViewRoot对应于 ViewRootImpl 类,它是连接 WindowManager和 DecorView 的纽带,View 的三大流程均是通过ViewRoot来完成的。在ActivityThread 中,当Activity 对象被创建完毕后,会将DecorView添加到Window中,同时会创建 ViewRootImpl 对象,并将ViewRootImpl对象和 DecorView建立关联。

如下源码:WindowManagerGlobal

root = new ViewRootImpl(view.getContext(), display);
root.setView(view, wparams, panelParentView);

View的绘制流程是从 ViewRoot 的performTraversals方法开始的,它经过measure,layout,和draw三个过程才能最终将一个View绘制出来,其中 measure 用来测量View的宽和高,layout用来确定View在父容器中的放置位置,而draw则负责将View绘制在屏幕上,针对performTraversals的 大致流程,如下图表示:


如图所示,perfrformTraversals 会依次调用 performMeasure,performLayout,performDraw这三个方法,这个三个方法分别完成顶级View 的measure,layout和 draw这三大流程,其中在  performMeasure 中会调用 measure方法,在measure方法中又会调用 onMeasure方法,在 onMeasure 方法中则会对所有的子元素进行 measure过程,这个时候 measure 流程就从父容器传递到子元素中了,这样也就完成了一次 measure过程。接着子元素会重复 父容器的 measure过程,如此反复就完成了整个 View树的遍历。

同理,performLayout 和 performDraw 的传递流程和 performMeasure 是类似的,唯一不同的是,performDraw 的传递过程是在 draw 方法中通过 dispatchDraw 来实现的,不过区别并不是很大。

Measure

measure过程决定了View的 宽/高,Measure完成以后,可以通过 getMeasuredWidth 和 getMeasuredHeight 方法来获取到View 测量后的宽/高,在几乎所有的情况下,它都等同于 View的最终 宽/高,(也可以重写 onSizeChanged),当然特殊情况除外。

Layout

Layout过程决定了 getLeft 和 getRight 来拿到View的四个顶点的位置,并可以通过 getWidth 和 getHeight 方法来拿到View 的最终宽/高。

Draw

Draw过程则决定了 View的显示,只有 draw方法完成以后,View的内容才能显示到屏幕上,但需要注意的是,应该尽量避免在 onDraw的过程中执行过多的循环操作。

另一个角度来看DecorView

网络异常,图片无法展示
|


DecorView 作为顶级的View,一般情况下 内部会包含一个 竖直方向的 LinearLayout,在这个 LinearLayout 里面有上下两个部分(具体的情况和Android版本及主题有关),上面是标题栏,下面是内容栏,在Activity 中我们通过 setContentView 所设置的布局文件其实就是被加到内容栏之中的,而内容栏的 id 是 content,因此可以理解为 Activity 指定布局的方法不叫 setView 而交 setContentView,因为我们的布局的确加到了 id 为 content 的 FrameLayout中。

获取content -ViewGroup

val content = findViewById<ViewGroup>(android.R.id.content)

获取setContentView中设置的View

content.getChildAt(0)

最后,DecorView其实是一个 FrameLayout,View层的事件都先经过 DecorView,然后才传递给我们的View.

目录
相关文章
|
人工智能 自然语言处理 算法
如何学习AIGC
【1月更文挑战第21天】如何学习AIGC
713 1
如何学习AIGC
|
机器学习/深度学习 传感器 计算机视觉
MotionBert论文解读及详细复现教程
MotionBert提出了一个统一视角来学习人体运动表示,并使用双流时空Transformer(DSTformer)网络作为运动编码器,能够全面、自适应地捕获骨骼关节之间的远程时空关系,实现在多个下游任务上的性能提升。
608 1
MotionBert论文解读及详细复现教程
|
SQL 数据管理 数据库
文章初学者指南:SQL新建数据库详细步骤与最佳实践
引言:在当今数字化的世界,数据库管理已经成为信息技术领域中不可或缺的一部分。作为广泛使用的数据库管理系统,SQL已经成为数据管理和信息检索的标准语言。本文将详细介绍如何使用SQL新建数据库,包括准备工作、具体步骤和最佳实践,帮助初学者快速上手。一、准备工作在开始新建数据库之前,你需要做好以下准备工作
870 3
|
存储 Java 开发者
【Java新纪元启航】JDK 22:解锁未命名变量与模式,让代码更简洁,思维更自由!
【9月更文挑战第7天】JDK 22带来的未命名变量与模式匹配的结合,是Java编程语言发展历程中的一个重要里程碑。它不仅简化了代码,提高了开发效率,更重要的是,它激发了我们对Java编程的新思考,让我们有机会以更加自由、更加创造性的方式解决问题。随着Java生态系统的不断演进,我们有理由相信,未来的Java将更加灵活、更加强大,为开发者们提供更加广阔的舞台。让我们携手并进,共同迎接Java新纪元的到来!
232 11
|
图形学
【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱1(附带项目源码)
【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱1(附带项目源码)
318 0
|
小程序 前端开发 JavaScript
微信小程序——解决异步问题
微信小程序——解决异步问题
741 0
|
弹性计算 大数据 测试技术
云服务器ECS租用多少钱价格表_2024年新版报价
云服务器ECS租用多少钱价格表_2024年新版报价,云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通用型g7、c8i、g8i等企业级实例规格
821 0
|
机器学习/深度学习 人工智能 编解码
阿里云PAI-Diffusion功能再升级,全链路支持模型调优,平均推理速度提升75%以上
本⽂首先介绍如何体验PAI-Diffusion模型以及其在线部署、加速推理能力。其次,我们简单回顾了PAI-Diffusion模型的架构,之后详细介绍了在EasyNLP算法框架中对上述模型进行调优的全链路支持。
阿里云PAI-Diffusion功能再升级,全链路支持模型调优,平均推理速度提升75%以上
|
缓存 自然语言处理 Kubernetes
数据缓存系列分享(四):开源大语言模型通义千问快速体验
本文将分享如何通过阿里云ECI的数据缓存秒级搭建开源大语言模型通义千问。
872 0
数据缓存系列分享(四):开源大语言模型通义千问快速体验
|
Java Spring
SpringMVC控制层private方法中出现注入的service对象空指针异常
一、现象 SpringMVC中controller里的private接口中注入的service层的bean为null,而同一个controller中访问修饰符为public和protected的方法不会出现这样的问题。