当前位置: 首页 > ops >正文

Flutter的三棵树

“三棵树”是 Flutter 渲染和构建UI的核心机制,理解它们对于掌握 Flutter 至关重要。这三棵树分别是:

  1. Widget 树

  2. Element 树

  3. RenderObject 树

它们协同工作,以实现 Flutter 的高性能渲染和高效的响应式编程模型。

Flutter 是声明式的UI,它只需要描述UI是什么样的,而不需要一步步地指挥框架如何去构建和更新这个界面。

为了更好的理解可先了解:命令式 UI 和 声明式 UI

一、Flutter的三棵树

1. Widget 树 (What to render)

  • 是什么:Widget 是你用代码声明的UI配置。它是一个不可变的(immutable)描述,告诉 Flutter 这部分UI应该长什么样子。你可以把它看作是一份蓝图

  • 特点

    • 轻量级:Widget 本身并不负责实际的渲染或状态管理,它只持有最终的配置信息(如颜色、字体、尺寸等)。

    • 不可变:一旦创建就不能修改。当UI需要变化时,你必须创建一个新的 Widget。这种immutability使得Widget的创建和销毁非常快速。

    • 组合性:复杂的UI由无数个简单的小Widget嵌套组合而成(如Column > Row > Container > Text)。

例子:这段代码就定义了一棵小小的 Widget 树。

Container( // Widgetcolor: Colors.blue,child: Center( // Widgetchild: Text('Hello World'), // Widget),
);

2. Element 树 (How to render & Where)

  • 是什么:Element 是 Widget 在UI树中具体位置的实例化体现。它是连接 Widget 和 RenderObject 的粘合剂,负责管理UI的更新和生命周期。

  • 特点

    • 可变且有状态:Element 是长寿命的,在UI重建时会持续存在(只要同一个位置的runtimeTypekey没变)。

    • 职责

      1. 挂载:它持有对对应 Widget 和 RenderObject 的引用。

      2. 比较:当UI重建,新的 Widget 树到来时,Element 会负责将新的 Widget 与它当前持有的旧 Widget 进行对比(Widget.canUpdate)。

      3. 更新:如果新的 Widget 和旧的 Widget 是同一类型(runtimeTypekey相同),Element 会更新自己持有的 Widget 引用,并告诉 RenderObject 是否需要更新(reconfigure)。

      4. 重建:如果对比失败,Element 会销毁旧的并创建新的 Element 和 RenderObject。

简单来说,Element 决定了是复用现有的UI结构,还是销毁重建。

3. RenderObject 树 (Actually rendering)

  • 是什么:RenderObject 是真正负责布局(Layout)和绘制(Paint) 的核心组件。它计算每个UI元素的大小和位置,并将它们绘制到屏幕上。

  • 特点

    • 重量级:布局和绘制的计算成本很高,因此 RenderObject 的创建和更新需要非常谨慎。

    • 核心方法

      • performLayout():计算自身和子节点的大小和位置。

      • paint():将自己绘制到画布(Canvas)上。

    • 持久化:只要有可能,Flutter 会极力避免重新创建和重新布局 RenderObject,以保持渲染性能的流畅。

大多数开发者通常不直接操作 RenderObject,而是通过熟悉的 Widget(如ContainerStackAlign)来间接使用它们。

二、三棵树如何协同工作?

让我们通过一个简单的计数器例子来看整个流程:

初始构建阶段

  1. 你编写了 MyHomePage Widget 树。

  2. Flutter 遍历你的 Widget 树,自上而下地创建对应的 Element

  3. 每个 Element 又会调用 Widget 的 createRenderObject() 方法,创建相应的 RenderObject

  4. 三棵树都构建完毕,RenderObject 树进行布局和绘制,UI显示在屏幕上。

更新阶段

(当你按下按钮,counter增加)

​​​​​​​​​​​​​​
  1. setState(() { _counter++; }) 被调用,标记该 StatefulWidget 的 Element 为“脏”状态。

  2. 下一帧到来时,Flutter 会触发重建对应的 Widget 子树。build 方法被再次调用,返回一棵新的 Text($_counter) Widget。

  3. 关键的对比过程(Diff)

    • 对应的 Element 会拿着这个新的 Text Widget,与它当前持有的旧的 Text Widget 进行比较。

    • 它发现两者的 runtimeType 都是 Text,并且都没有设置 key,所以可以更新。

  4. 高效的更新

    • Element 简单地更新它持有的 Widget 引用为新的 Widget。

    • 然后,Element 会通知它对应的 RenderObject:“配置有变化,你需要更新了”。

    • RenderObject 检查发现只是文本内容变了,它可能会标记自己需要重绘(repaint),但通常不需要重新布局(relayout)(因为文字大小可能没变)。

  5. 下一帧,RenderObject 只进行必要的重绘,新的数字就显示出来了。

三、为什么需要三棵树? (优点)

  1. 性能优化:将轻量级的、不可变的 Widget 与重量级的、可变的 RenderObject 分离。UI的频繁重建(创建新Widget)成本极低,而真正昂贵的布局和绘制过程只有在必要时才进行。

  2. 高效的响应式编程:通过 Element 树的 Diff 算法,Flutter 可以精确地知道UI的哪一部分发生了变化,从而只更新必要的 RenderObject,而不是整个界面。这比传统的命令式UI(如Android/iOS原生)手动操作View要高效得多。

  3. 逻辑与渲染分离:开发者只需关心如何用 Widget 描述UI(声明式),而无需关心具体的渲染细节和更新逻辑,框架帮你处理了所有复杂性。

四、总结

角色特点职责
Widget 树蓝图/配置轻量、不可变描述UI元素应该是什么样子
Element 树粘合剂/管理者可变、长寿命管理Widget的更新,决定是复用还是重建UI
RenderObject 树渲染工人重量级、持久负责实际的布局、绘制工作,计算尺寸和位置,渲染到屏幕

简单记忆Widget 是配置,Element 是管家,RenderObject 是干活的。 管家(Element)根据新的图纸(Widget)来决定是让工人(RenderObject)在原基础上修改,还是直接换一个新工人。

http://www.xdnf.cn/news/19979.html

相关文章:

  • 【STM32外设】DAC
  • Big Data Analysis
  • 某头部能源集团“数据治理”到“数智应用”跃迁案例剖析
  • Ubuntu中使用nginx-rtmp-module实现视频点播
  • mac 安装 nginx
  • Day36 TCP客户端编程 HTTP协议解析 获取实时天气信息
  • 如何选择适合的实验室铸铁地板和铸铁试验平板?专业人士帮助指南
  • 【开题答辩全过程】以 基于Android的点餐系统为例,包含答辩的问题和答案
  • 《sklearn机器学习——多标签排序指标》
  • Conda 使用py环境隔离
  • 新后端漏洞(上)- H2 Database Console 未授权访问
  • 高级RAG策略学习(四)——上下文窗口增强检索RAG
  • 耐达讯自动化RS485与Profinet双向奔赴,伺服驱动器连接“稳稳拿捏”
  • 第24节:3D音频与空间音效实现
  • 如何使用宝塔API批量操作Windows目录文件:从获取文件列表到删除文件的完整示例
  • 【第三方网站测试:WEB安全测试中HTTP响应头安全配置的检测的几个要点】
  • 【Web安全】命令注入与代码注入漏洞解析及安全测试指南
  • 极致效率:用 Copilot 加速你的 Android 开发
  • Linux内核网络安全序列号生成机制解析
  • 复合机器人能否更换末端执行器?
  • threejs入门学习日记
  • 分布式微服务--ZooKeeper作为分布式锁
  • Spring如何解决循环依赖:深入理解三级缓存机制
  • Android13 系统源码核心目录解析
  • css margin外边距重叠/塌陷问题
  • AI时代企业获取精准流量与实现增长的GEO新引擎
  • Android14实现Settings左右分屏显示的 代码修改
  • 智能相机还是视觉系统?一文讲透工业视觉两大选择的取舍之道
  • MCP驱动企业微信智能中枢:企业级机器人服务构建全攻略
  • 嘎嘎厉害!耐达讯自动化RS485转Profinet网关就是食品温控的“天选之子”