Skip to content

flutter的渲染机制笔记

🕒 发布时间: 🕒 阅读时间: 0 分钟✍︎ 文章字数: 0

逐步解析

1. Widget 树

在 Flutter 中,UI 是由 Widget 组成的树状结构。每个 Widget 代表 UI 的一部分,可以是可见的(如按钮、文本)或不可见的(如布局管理器),也可以说每个Widget描述了UI的一部分。

2. Element 树

每个 Widget 都有一个或多个对应的 Element。Element 树是 Widget 树的一个实例化版本,它持有对 Widget 的引用,并且管理 Widget 的生命周期和状态。Widget可以看作是Element的一种配置信息,Element 负责调用 RenderObject 进行绘制,确保 Widget 的视觉表现符合预期。

3. RenderObject 树

RenderObject 树是 Element 树的一个子集,它包含所有需要实际渲染的元素。RenderObject 负责计算布局、绘制和处理输入事件。

5. 渲染流程

Flutter 的渲染流程可以分为以下几个步骤:

a. 构建(Build)

当应用程序启动或状态发生变化时,Flutter 会重新构建 Widget 树。这个过程会创建或更新 Element 树。

b. 布局(Layout)

Element 树中的 RenderObject 会计算自己的布局。这个过程是自顶向下的,每个 RenderObject 会根据其子节点的约束来确定自己的大小和位置。

c. 绘制(Paint)

布局完成后,RenderObject 会进行绘制。这个过程是自底向上的,每个 RenderObject 会绘制自己的内容,并可能调用子节点的绘制方法。

d. 合成(Compositing)

绘制完成后,Flutter 会将所有绘制的内容合成为一个或多个图层。这些图层最终会被发送到 GPU 进行渲染。

6. 增量更新

Flutter 使用增量更新的方式来优化渲染性能。当状态发生变化时,Flutter 只会重新构建受影响的 Widget 和 Element,而不是整个树。这使得 Flutter 能够快速响应变化,同时保持高性能。

7. 性能优化

Flutter 3.0 还引入了一些性能优化,如改进的文本渲染、更高效的图像缓存和更好的内存管理。这些优化使得 Flutter 应用在各种设备上都能保持流畅的性能。

FAQ

Q1: 增量更新的机制是什么样的?

A: Flutter 会根据状态变化,标记哪些 Widget 需要重新构建。这个过程是基于 Flutter 的响应式编程模型,其中每个 Widget 都有一个对应的状态对象(State),当状态对象发生变化时,相关的 Widget 会被标记为“dirty”。

Q2: 增量更新的分析是在哪个生命周期?

A: 增量更新的分析主要在构建(Build)和更新(Update)环节中进行。Flutter 通过检测状态变化、标记需要更新的 Widget、重新构建 Widget 树、更新 Element 树和 RenderObject 树,以及执行增量布局和绘制,来实现高效的增量更新。这种机制确保了 Flutter 应用能够快速响应状态变化,同时保持高性能和流畅的用户体验。

Q3: flutter的组件状态更新了,是如何渲染的?

A: 当组件自身的状态更新时,Flutter 会重新构建 Widget 树。这是因为 Flutter 的渲染机制是自顶向下的,当一个组件的状态更新时,其所有子组件都会被重新构建和渲染。这种机制确保了状态变化能够正确地反映在 UI 上,同时保持了高效的增量更新。

Q4: flutter的更新是自顶向下的,性能方面的影响大吗?

A: 更新出来的RenderObject不一定会被实际绘制出来,渲染机制会判断是否需要实际绘制。
渲染机制主要可以总结为以下几点:

  1. 增量更新
    • Flutter 使用增量更新的策略,这意味着只有实际发生变化的部分才会被重新绘制。
    • 当组件状态更新时,Flutter 会重新构建 Widget 树,并更新对应的 Element 树和 RenderObject 树。
    • 但是,如果更新的内容没有导致视觉上的变化(例如,更新的是一些内部状态或非视觉属性),那么对应的 RenderObject 可能不会被重新绘制。
  2. 脏标记(Dirty Marking)
    • Flutter 使用脏标记来跟踪需要重新绘制的 RenderObject。
    • 当组件状态更新时,Flutter 会标记相关的 RenderObject 为“dirty”,表示它们需要重新绘制。
    • 但是,如果更新的内容没有导致视觉上的变化,Flutter 可能会跳过这些 RenderObject 的重新绘制。
  3. 性能优化
    • Flutter 在渲染过程中会进行各种性能优化,以确保高效和流畅的用户体验。
    • 例如,Flutter 会尽可能地复用现有的 RenderObject,而不是每次都创建新的实例。
    • 此外,Flutter 还会使用一些技术(如 const 构造函数、Key 等)来进一步优化渲染过程。

Q5: 为啥都是自顶向下,React的渲染机制会容易出现性能问题?

这里先不谈RN,只比较React本身。Flutter和React 18+的渲染机制真的挺像的,都是自顶向下更新,并且都有增量更新的机制,都会批处理多个渲染操作,减少实际渲染次数。为啥react性能经常被吐槽?react更新粒度和flutter有什么不同?
A:

Flutter 的更新机制

Flutter 通过其“三兄弟”(Widget、Element、RenderObject)的协作,实现了高效的更新机制:

  1. Widget:描述 UI 的配置信息,是不可变的。当状态变化时,Flutter 会重新构建 Widget 树。
  2. Element:是 Widget 树的实例化对象,管理 Widget 的生命周期和状态。Element 树是可变的,Flutter 通过比较新旧 Widget 树来更新 Element 树,标记哪些 Element 需要更新。
  3. RenderObject:负责实际的布局和绘制。只有标记为“dirty”的 RenderObject 才会重新布局和绘制。

这种机制使得 Flutter 能够快速定位并更新真正需要在页面上变化的部分,从而实现高效的增量更新。

React 的更新机制

React 其虚拟 DOM 的比较机制依赖于浅比较,不会自动进行深层次的计算和比较,且默认行为是从上往下重新渲染整个组件树,需要开发者手动进行优化以避免不必要的重渲染。 react并没有复用vdom的可能是要考虑副作用,react函数式组件的理想情况ui=f(state/data),但是实际上ui开发是经常会有副作用的,纯函数实现不太实际。

总结:Flutter相比较React,更新粒度较小,能精准更新页面上需要变化的部分。

参考资料

Last updated: