聊聊 Jetpack Compose 原理 -- Compose 是如何将数据转换成 UI 的?

news2024/11/27 14:38:21

Compose 是一个声明式的 UI 框架,提供了很多开箱即用的组件,比如 Text()、Button、Image() 等等,Compose 会经过几个不同的阶段,最终渲染出 UI 界面。

此转换过程分为【三个阶段】

  1. 组合: 显示什么
  2. 布局: 放在哪里
  3. 绘制: 如何渲染

这三个阶段是逐一执行的,流程如下:

在这里插入图片描述

组合阶段

在组合阶段,Compose 运行时会执行代码中定义的可组合函数,最终会生成一棵视图树。这个视图树由一个个布局节点(LayoutNode)组成。比如 Text()、Button() 都对应一个 LayoutNode,这些 LayoutNode 持有组件的所有信息。

在这里插入图片描述

更形象一点的结构如下:
在这里插入图片描述

这是一个非常简单的示例,但有时候我们定义的可组合项包含逻辑和控制流,而 Compose 会在不同状态的情况下生成不同的树。

布局阶段

布局阶段,对于视图树中的每个 LayoutNode 节点进行宽高尺寸测量并完成位置摆放,布局元素都会根据 2D 坐标来测量并放置自己及其所有子元素。

在这里插入图片描述

其实 Compose 的布局阶段和传统的 View 系统很像(测量、布局、绘制),唯独多了一个“组合阶段”,而 Compose 把 测量和布局 统一放入了“布局阶段”

在布局阶段,使用以下 3 步算法遍历 LayoutNode 树:

  1. 测量子节点: 每一个节点会测量它的子节点,如果有的话。
  2. 决定自己的大小: 基于这些测量,节点决定自己的大小。
  3. 放置子节点: 每个子节点都相对于节点自身的位置进行放置。

布局阶段结束后,每个 LayoutNode 都将分配一个 宽度高度,以及一个应该绘制的 xy 坐标。

现在我们分析下面这个简单示例的布局流程。

在这里插入图片描述

🔵 Row 测量其子项。

      🟢 首先,测量 Image。它没有任何子项,因此它决定自己的大小并将其报告给 Row。

      🟢 其次,测量 Column。它需要先测量自己的子项。

            🟠 第一个 Text 被测量。它没有任何子项,因此它决定自己的大小并将其报告给 Column。

            🟠 第二个 Text 被测量。它没有任何子项,因此它决定自己的大小并将其报告给 Column。

      🟢 Column 使用子测量值来决定自己的大小。它使用最大子宽度及其子项的高度之和。

      🟢 Column 将其子项放置在相对于自身的位置,将它们垂直放置在彼此下方。

🔵 Row 使用子尺寸来决定自己的尺寸。它使用最大子高度和子宽度的总和。然后它放置它的子项。

看到这,是不是发现个很牛逼的事? 我们只访问了每个节点一次。通过视图树的一次遍历,我们就可以测量和放置所有节点。这对性能来说就很重要了!当树中节点的数量增加时,遍历它所花费的时间只会以线性方式增加。相比之下,如果我们多次访问每个节点,遍历时间则会以呈指数级增加。

绘制阶段

绘制阶段,树中的每个节点都在屏幕上绘制其像素。

在这里插入图片描述

上面我们说过,在布局阶段结束后,所有布局节点会得到它们的 宽度高度,以及 xy 坐标。所以现在就可以进入绘制阶段了。

绘制阶段会从上到下再次遍历树,每个节点依次在屏幕上绘制自己。

在这里插入图片描述

首先 Row 将绘制它可能具有的任何内容,例如背景色。然后 Image 将绘制自己,然后是 Column,然后是第一个和第二个 Text。

Modifier 修饰符

上面我们给的简单代码示例都只是用了一些 Compose 提供给我们的现场的组件,实际开发过程中,会有一个大神级别一样的修饰符随处可见,它就是:Modifier 修饰符。

比如:Modifier.padding 是用来给组件设置边距的,它本质上是一个 LayoutModifier,而 LayoutModifier 会影响组件的测量和布局效果,会影响到组合项的整体 UI 效果。具体如何影响,这篇文章我们不讲它的深层次原理,而只是探讨思维模型。

所以,如果你想了解 LayoutModifier 的原理,可以阅读 聊聊 Jetpack Compose 原理 – LayoutModifier 和 Modifier.layout 这篇文章。

回到正题,如果我们加了 Modifier 修饰符,那么在最终生成的视图树中,可以将 Modifier 修饰符可视化为布局节点的包装节点:

在这里插入图片描述

当我们链接多个修饰符时,每个修饰符节点包裹链的其余部分和其中的布局节点。 例如,当我们链接一个 clip 和一个 size 修饰符时,clip 修饰符节点包裹 size 修饰符节点,然后包裹 Image 布局节点。

这里你可能有疑问,为什么不是先 clip 然后 size,而是先 size 然后在 clip?看完 聊聊 Jetpack Compose 原理 – LayoutModifier 和 Modifier.layout 这篇文章你就懂了。

接着说,在布局阶段,我们用来遍历树的算法保持不变,但 每个修饰符节点也会被访问。这样,修饰符可以更改其包裹的 修饰符 或 布局节点 的 大小要求位置

如果我们看一下 Image 可组合项的实现(底层更细的实现),实际上可以看到它本身由包裹单个布局节点的修饰符链组成。类似地,Text 可组合项也是通过包含布局节点的修饰符链实现的。最后,Row 和 Column 的实现只是描述如何布置其子节点的布局节点:

在这里插入图片描述

看不懂这张图?没事,这些细节原理都会有文章输出,比如我刚刚提到了两次的原理文章。

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

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

相关文章

【MATLAB源码-第93期】基于matlab的白鲸优化算法(BWO)和鲸鱼优化算法(WOA)机器人栅格路径规划对比。

操作环境: MATLAB 2022a 1、算法描述 白鲸优化算法(BWO) 白鲸优化算法是受到白鲸捕食和迁徙行为启发的一种算法。其主要特点和步骤包括: 1. 搜索食物(全局搜索):算法模仿白鲸寻找食物的行为。…

西安安泰——ATA-1220E宽带放大器

ATA-1220E宽带放大器简介 ATA-1220E是一款可放大交直流信号的差分通道宽带放大器。其最大输出电压 60Vp-p(30Vp),最大输出电流1Ap(>50Hz)。电压增益数控可调,一键保存设置,提供了方便简洁的操作选择,可…

公有云迁移研究——AWS Route53

大纲 1 什么是Route 532 Route 53能做些什么# 3 通过DNS托管来实现分流3.1 创建DNS托管3.2 对托管创建记录对流量进行分配 4 通过流量策略来对流量进行分流4.1 创建流量策略 5 对比两者的区别6 推荐 在给客户从本地机房往AWS迁移的过程中,我们接到如下需求&#xff…

Leetcode.2477 到达首都的最少油耗

题目链接 Leetcode.2477 到达首都的最少油耗 rating : 2012 题目描述 给你一棵 n n n 个节点的树(一个无向、连通、无环图),每个节点表示一个城市,编号从 0 0 0 到 n − 1 n - 1 n−1 ,且恰好有 n − 1 n - 1 n−…

GNN Maximum Flow Problem (From Shusen Wang)

Maximum Flow Problem ShusenWang 图数据结构和算法课程笔记 Slides Maximum Flow Problem Description Naive Algorithm Residual Capacity - FlowLeft: Original GraphRight: Residual Graph - Bottleneck capacity 2- Iteration 2:- Find an augmenting path: s -&g…

Rust的From与Into Trait

Into的本质是调用了From Trait 的方法。 From是底层的方法,把From实现了,Into的实现,编译器会自动根据From Trait生成Into Trait的代码 编译器自动类型推导出Into Trait的U的类型,调用了U类型的From的方法,实现其他类…

解决HTTP错误500.19 - internal server error -内部服务器错误的终极指南

在开发和维护网络应用程序时,难免会遇到各种HTTP错误代码。其中,HTTP错误500.19 - 内部服务器错误可谓是最令人头痛的问题之一。当你的应用程序遇到这个错误时,它似乎就像一道墙壁,挡住了你前进的道路。但别担心,本篇技…

JDK 历史版本下载以及指定版本应用

参考: 官网下载JAVA的JDK11版本(下载、安装、配置环境变量)_java11下载-CSDN博客 Gradle:执行命令时指定 JDK 版本 - 微酷网 下载 打开官网地址 Java Downloads | Oracle 当前版本在这里,但是我们要下载历史版本 选…

Python中检查字符串是否仅包含字母的多种方法:深入探究

更多资料获取 📚 个人网站:ipengtao.com 随着Python在数据处理和字符串操作方面的广泛应用,经常需要对字符串进行验证,确认其是否仅包含字母。本文将探讨Python中的多种方法来检查字符串是否只由字母组成,以及它们的应…

Windows下安装Git和Git小乌龟

目录 Git简介 Git安装 Git小乌龟简介 Git小乌龟安装 Git简介 Git是一个开源的分布式版本控制系统,可以有效、高速地进行从很小到非常大的项目的版本管理。Git支持将本地仓库与远程仓库进行关联,实现多人协作开发。由于具有分布式版本控制、高效性、灵…

C语言之if语句在生活中的应用

目前为止我们已经把基础的if语句,但还要学以致用。下面我们数据用的都是整形,您也可以选择浮点型。 滴滴打车 今天我要出去玩,打了一辆出租车,师傅告诉我五公里内起步价10元,超过5公里后,每公里3元&#x…

代码随想录算法训练营 ---第五十五天

今天是 动态规划:编辑距离问题。 第一题: 简介: 动态规划五部曲: 1.确定dp数组的含义 dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。 2.确定递推公…

【Maven】清理 maven 仓库

初始情况下,我们的本地仓库是没有任何jar包的,此时会从私服去下载(如果没有配置,就直接从中央仓库去下载)。 可能由于网络的原因,jar包下载不完全,这些不完整的jar包都是以lastUpdated结尾。此…

Jmeter 接口-加密信息发送(一百九十九)

方式1:使用函数助手 比如MD5加密方式: 如图,需要对${user}进行MD5加密 1、打开函数助手,找到MD5,输入需要加密的值 2、将${__MD5(${user},)}放到请求中 3、查看请求,请求成功 方式2:导入jar包…

Android画布Canvas绘制drawBitmap基于源Rect和目的Rect,Kotlin

Android画布Canvas绘制drawBitmap基于源Rect和目的Rect&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <androidx.appcompat.widget.LinearLayoutCompat xmlns:android"http://schemas.android.com/apk/res/android"xmlns…

CTF特训日记day(4-6)

来复现一下2022QWB决赛的RDP题目 这两天腰疼去了趟医院 题目要求我们攻击XRDP程序&#xff0c;从而达到本地提权的效果。 首先观察XRDP程序的版本信息 rootRDP:/home/rdp/Desktop# xrdp-sesman -version xrdp-sesman 0.9.18The xrdp session managerCopyright (C) 2004-2020…

Python小案例:打印三角形

打印不同形状以及方向的三角形 分析 需要利用循环打印规则 代码部分 userint(input("请输入打印行数&#xff1a;"))# 打印正向直角三角形 def Triangls_01(user_input):for i in range(1,user_input):print("*"*i)# 打印倒向直角三角形 def Triangls_0…

用友U8 Cloud RegisterServlet SQL注入漏洞复现

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友U8 Cloud RegisterServlet接口处存在SQL注入漏洞,未授权的攻击者可通过此漏洞获取数据库权限,从而盗取用户数据,造成用户信息泄露。 …

集成测试如何做?

今天学习下如何进行集成测试。 什么是集成测试? 集成测试被定义为一种测试类型&#xff0c;其中软件模块在逻辑上集成并作为一个组进行测试。一个典型的软件项目由多个软件模块组成&#xff0c;由不同的程序员编码。此级别测试的目的是在集成这些软件模块时&#xff0c;暴露…

HarmonyOS4.0开发应用——【ArkUI组件使用】

ArkUI组件使用 这里会详细演示以下组件使用: ImageTextTextInputButtonSliderColumn&&RowList自定义组件以及相关函数使用 Image 可以是网络图片、可以是本地图片、也可以是像素图 Image("https://ts1.cn.mm.bing.net/th?idOIP-C.cYA-_PINA-ND9OeBaolDTwHaHa&…