首页 > 其他分享 >Jetpack Compose 如何布局解析

Jetpack Compose 如何布局解析

时间:2024-11-23 22:01:02浏览次数:8  
标签:Compose composer Jetpack Composable UI Composer 解析 节点

文章目录


前言

Jetpack Compose 的布局解析包含以下核心环节:编译器处理UI 树的构建与状态管理测量与布局、以及重组机制。以下是结合源码的深入解析。

1、@Composable 函数的编译器处理

@Composable 是 Compose 中的核心注解,用于标记 Composable 函数,表示该函数会参与 Compose 的重组机制。

编译器的作用
Compose 编译器会将标注为 @Composable 的函数转换为支持 Composer 和 Recomposition 的代码。以下是编译前后的对比:

原始代码:

@Composable
fun Greeting(name: String) {
    Text("Hello, $name!")
}

编译后的伪代码:

fun Greeting(name: String, composer: Composer?, key: Int) {
    composer.startRestartGroup(key) // 开始重组
    if (composer.shouldSkip()) {    // 判断是否跳过重组
        composer.skipCurrentGroup()
    } else {
        Text("Hello, $name!")       // 渲染 Text 组件
    }
    composer.endRestartGroup()      // 结束重组
}

关键源码位置
Composer 类:

  • 位于 androidx.compose.runtime 包中,是 Compose Runtime 的核心组件。
  • 负责管理重组范围(startRestartGroup/endRestartGroup)和跳过未改变的 UI 代码。

2、UI 树的构建与状态管理

Compose 使用 SlotTable 和 Composer 构建 UI 树并管理其状态。

SlotTable 的作用
SlotTable 是一个内部的数据结构,用于记录 UI 树的状态和结构。它包含了以下内容:

  • Key:用于标识每个 Composable 函数。
  • Value:存储与节点相关的数据,例如子节点的引用、布局信息等。

工作流程:

1、Composer 将 Composable 函数解析为节点。
2、解析结果存储在 SlotTable 中。

val slotTable = SlotTable()
val composer = Composer(slotTable)
composer.startRestartGroup(1234) // 开始解析 Key 为 1234 的组
Text("Hello, Compose!")
composer.endRestartGroup()       // 结束解析

相关源码位置

  • SlotTable 类:
    位于 androidx.compose.runtime 包中,核心方法包括 ensureCapacity 和 recordGroup。
  • Composer 类:
    管理 SlotTable 的增删改操作。

3、测量与布局

Compose 使用 LayoutNode 和 MeasurePolicy 实现测量与布局。
测量流程
Compose 布局解析的核心在于 测量约束传递子节点布局

  • Constraints:描述宽度、高度的限制条件。
  • MeasurePolicy:定义节点的测量逻辑,包括如何计算子节点的位置。

源码示例:
以下是 Compose 内部如何实现 Column 布局的一个简化示例:

val measurePolicy = MeasurePolicy { measurables, constraints ->
    var totalHeight = 0
    val placeables = measurables.map { measurable ->
        val placeable = measurable.measure(constraints)
        totalHeight += placeable.height
        placeable
    }
    layout(constraints.maxWidth, totalHeight) {
        var yPosition = 0
        placeables.forEach { placeable ->
            placeable.place(0, yPosition)
            yPosition += placeable.height
        }
    }
}
  • measurables.measure(constraints):对子节点进行测量。
  • layout:定义自身大小并放置子节点。
    关键源码位置
    MeasurePolicy 类:
    位于 androidx.compose.ui.layout.MeasurePolicy。
    LayoutNode 类:
    位于 androidx.compose.ui.node.LayoutNode。

4、重组机制(Recomposition)

重组是 Compose 的核心优化机制。它通过比较 SlotTable 的状态,仅更新发生变化的部分 UI。

状态与重组
Compose 使用 MutableState 和 remember 来追踪状态。当状态变化时,Composer 会标记对应的 UI 节点需要重新执行。

示例:

@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }
    Button(onClick = { count++ }) {
        Text("Count: $count")
    }
}

当 count 发生变化时,Composer 仅重组 Text 节点,而不会更新其他部分。

伪代码:

fun Counter(composer: Composer?) {
    composer.startRestartGroup(key = 123)
    val count = composer.remember { mutableStateOf(0) }
    Button(onClick = { count.value++ }) {
        Text("Count: ${count.value}")
    }
    composer.endRestartGroup()
}

composer.shouldSkip():检查节点是否需要跳过。
remember:记录状态,用于触发重组。

5、性能优化机制

为了减少不必要的重组,Compose 提供了以下优化工具:
1、derivedStateOf:派生状态,用于合并多个状态变化,避免频繁重组。
2、remember:缓存计算结果,避免重复执行。

示例:

val derivedState = derivedStateOf { count * 2 }
Text("Derived Count: ${derivedState.value}")

总结

1、编译器阶段:
转换 @Composable 函数,生成支持 Composer 和重组的代码。
2、构建 UI 树:
使用 Composer 构建 SlotTable,记录 UI 组件信息。
3、测量布局:
通过 Constraints 和 MeasurePolicy 确定组件大小与位置。
4、状态更新:
管理组件状态,触发高效重组,更新变化的 UI 节点。

Compose 的解析流程从代码到最终渲染,严格遵循上述四步,使其能够在保持声明式编程风格的同时,达到高性能的动态更新能力。

标签:Compose,composer,Jetpack,Composable,UI,Composer,解析,节点
From: https://blog.csdn.net/weixin_44780781/article/details/143997469

相关文章

  • MySQL UPDATE语句执行链路解析
    文章目录引言1.总览:UPDATE语句的执行链路2.客户端发起请求2.1SQL请求的形成2.2MySQL通信协议3.连接器模块3.1连接管3.2会话上下文4.SQL解析器4.1语法解析4.2语法错误处理5.查询优化器5.1查询优化的核心概念5.2优化器生成执行计划的步骤5.3优化器常见挑......
  • 全面解析:单列集合Collection和双列集合Map
            Java中的集合(Collection)是一个框架,用于存储、操作数据。集合框架包括了许多接口和类,用于表示数据的存储方式。集合主要分为两大类:Collection和Map。单列集合Collection的继承体系图:Collection接口提供了一些通用的方法,用于操作集合的元素。常用的方法......
  • 【计算机网络】本机DNS服务器与解析地址查看
    本机DNS服务器与解析地址查看1.DNS服务器地址1.1Windows1.2Linux1.3macOS2.本地DNS解析缓存2.1Windows2.2Linux2.3macOS3.本地`hosts`文件3.1文件路径3.2格式说明3.3应用场景4.检测实际使用的DNS服务器DNS(域名系统)是互联网的重要组成部分,它将......
  • 深入解析 Web 应用中的 CHIPS(Partitioned Cookie Attribute)
    深入解析Web应用中的CHIPS(PartitionedCookieAttribute)最新发现flask3.1.0的版本引入了新的特性:对CHIPS的支持。不少同学对这个可能有点陌生,本文带大家了解一下。为了在隐私保护和功能需求之间取得平衡,Google推出了CHIPS(CookiesHavingIndependentPartitioned......
  • Flink普通API之Source使用全解析
    Flink普通API之Source使用全解析一、引言在Flink的流式计算世界里,Source作为数据的源头起着至关重要的作用。它能够为Flink任务提供数据输入,无论是批处理还是流处理场景,合适的Source选择与使用都能让数据处理流程顺利开启。本文将深入探讨Flink中Source的相关知识,包括预定......
  • 2024年09月CCF-GESP编程能力等级认证Scratch图形化编程一级真题解析
    本文收录于《Scratch等级认证CCF-GESP图形化真题解析》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。一、单选题(每题3分,共30分)第1题据有关资料,山东大学于1972年研制成功DJL-1计算机,并于1973年投入运行,其综合性能居当时全国第三位。DJL-1计算机运算控......
  • cornerstone中raft_server源码解析
    1.概述cornerstone中核心即为raft_server的实现。在raft里面有follower,leader,candidate三种角色,且角色身份还可以相互切换。写三个类follower,leader,candidate显得没必要,因为三个类可以共享许多成员变量,如term,log_store等等。因此在cornerstone中抽象出raft_server这一个类,而raf......
  • 全面解析Shodan:网络安全中的设备扫描与漏洞识别利器
    声明!学习视频来自B站up主**泷羽sec**有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!!!!有兴趣的小伙伴可以点击下面连接进入b站主页[B站......
  • x-cmd pkg | nexttrace - 可视化路由跟踪工具,支持多种 IP 数据库,助你深入解析网络路径
    目录简介快速上手安装使用功能特点竞品和相关作品进一步阅读简介nexttrace是github.com/nxtrace用Go开发的可视化路由跟踪工具,用于分析从源到目标的网络路径。它默认使用ICMP协议发起TraceRoute请求,支持IPv4和IPv6,支持指定网卡进行路由跟踪,支持TTL控......
  • HarmonyOS Next 安全更新机制全解析感悟
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。一、安全更新的重要性(一)对系统稳定......