Flutter渲染机制

Flutter渲染机制

学flutter有大半年了,现在写点flutter相关的知识,一是为了巩固自己,二是希望对大家深入理解flutter有所帮助,本篇文章参考陈航写的Flutter核心技术与实战。

flutter界面渲染过程

app界面的每一个widget都是以树的形式组织的,Flutter通过树中的每个widget创建不同类型的渲染对象,组成渲染对象树,其展示过程分为布局、绘制、合成和渲染四个阶段

布局

Flutter采用深度优先机制遍历渲染对象树,决定各渲染对象在屏幕上的位置和尺寸。

绘制

布局过程后,渲染对象树中的每个节点都有了明确的位置和尺寸,Flutter会把所有渲染对象绘制在不同图层,与布局过程一样,绘制过程也是深度优化遍历,即先绘制本身,再绘制子节点。

合并

合并是为了简化渲染树,提高渲染效率。因为一个app业务多了,页面也会很复杂,也会有很多重复渲染的图层,所以要将所有图层根据大小、层级、透明度等规则计算出最终需要显示的效果。

渲染

合并完成后,Flutter会将最终的图层数据交给Skia引擎加工成二维图像数据,最后交给GPU进行渲染,完成界面的展示

Widget的渲染过程

前面说到整个界面的渲染过程,可能比较抽象,这里通过界面中widget的渲染,从源代码分析Flutter的渲染过程。

大家应该知道视图树可以结构化的组织视图数据,提供给渲染引擎。而Flutter把视图数据的组织和渲染抽象为三部分,即Widget、Element和RenderObject。

Widget

Flutter将Widget设计成不可变的,这意味着当widget中视图渲染的配置信息发生改变时,Flutter会用重建Widget树的方式进行数据更新,而不是用命令修改来更新数据。这样就会有个问题,就是会涉及大量对象的销毁和创建,对垃圾回收造成压力。

Element

Element是Widget的一个实例化对象,他承载了视图构建的上下文数据,是连接结构化的配置信息到完成渲染的桥梁

这里从源码看,Flutter渲染过程可以分为三步:
1.通过Widget树生成对应的Element树。
2.创建相应的RenderObject并关联到Element.renderObject属性上。
3.构建成RenderObject树,完成最终的渲染。

根据渲染过程可以看到Element同时持有Widget和RenderObject,所以说它是桥梁。并且中间层Element的加入,极大的减少了渲染带来的的性能损耗。

为什么这么说呢?
因为Widget是不可变的,但是Element是可变的。Element树这一层将Widget树的变化做了抽象,可以只将真正需要修改的部分同步到真实的RendenrObject树中,最大程度降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个渲染视图树进行重建。

RenderObject

RenderObject是主要负责实现视图渲染的对象。
前面说到的渲染对象树在Flutter的展示过程分为布局、绘制、合并和渲染四个阶段。其中的布局和绘制就是在RenderObject中完成。

RenderObjectWidget

abstract class RenderObjectWidget extends Widget {
  @override
  RenderObjectElement createElement();
  @protected
  RenderObject createRenderObject(BuildContext context);
  @protected
  void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
  ...
}

RenderObjectWidget是一个抽象类,通过RenderObjectWidget的源码可以看到,这个类同时拥有创建Element、RenderObject以及更新RenderObject的方法。

实际上,RenderObjectWidget本身并不负责这些。

对于Element的创建,Flutter会在遍历Widget树时,调用createElement去同步Widget自身配置信息,从而生成对应节点的Element对象。

对于RenderObject的创建与更新,其实是在RenderObjectElement类中完成的。

abstract class RenderObjectElement extends Element {
  RenderObject _renderObject;

  @override
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _renderObject = widget.createRenderObject(this);
    attachRenderObject(newSlot);
    _dirty = false;
  }
   
  @override
  void update(covariant RenderObjectWidget newWidget) {
    super.update(newWidget);
    widget.updateRenderObject(this, renderObject);
    _dirty = false;
  }
  ...
}

在Element创建完毕后,Flutter会调用Element的mount方法,在这个方法里会完成与之关联的RenderObject对象的创建,以及与渲染树的插入。

如果Widget的配置数据发生了改变,那么持有该Widget的Element节点也会被标记为dirty。在下一个周期的绘制时,Flutter就会触发Element树的更新,并使用最新的Widget数据更新自身以及关联的RenderObject对象。然后便会进入到Layout和Paint流程。

abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget {
  ...
  void layout(Constraints constraints, { bool parentUsesSize = false }) {...}
  
  void paint(PaintingContext context, Offset offset) { }
}

布局和绘制完成后,接下来就交给Skia引擎了。

总结

介绍了Flutter界面渲染过程和Widget的渲染过程,可以看出Widget和Element是一一对应的,RenderObject不是,只有实际需要布局和绘制的控件才会有RenderObject

最后希望这篇文章对你学习Flutter有所帮助。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter渲染机制可以从源码角度来理解。Flutter渲染与两个线程直接相关,分别是UI线程和GPU线程。UI线程负责执行Dart root isolate代码,并将其转换为Layer tree。 Layer 是 Flutter Framework 中的一个重要概念,它代表了一块矩形区域,可以包含图形、文本、图片等内容。这些 Layer 最终会被提交到 Engine 中进行绘制。 Layer 的工作原理是将所有的绘制操作转化为一系列的绘制指令,然后将这些指令传递给 GPU 线程进行绘制。 Flutter Framework 中的绘制过程经过多个步骤,包括布局、绘制、合成等,最终将所有的 Layer 组合在一起形成最终的界面。通过理解 Flutter渲染原理,开发者可以更清晰地了解应用程序的渲染过程,并进行性能优化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Flutter渲染机制—UI线程](https://download.csdn.net/download/weixin_38550834/15446392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Flutter 画面渲染的全面解析](https://blog.csdn.net/chengjiamei/article/details/107974790)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值