Flutter_02_原理概述

Flutter、Golang、Python、编译原理、算法、Chrome原理学习系列文章抢先看请关注【码农帮派】:

 

Flutter重写了一套包括底层渲染逻辑 + 上层开发语言的完整方案,保证了:

  • 高保真:保证视图在Android和IOS平台上高度一致

  • 高性能:代码执行的效率媲美原生App的体验

Flutter与其他跨平台方案的区别:

  • RN之类的框架,通过JavaScript虚拟机调用系统原生组件,由Android和IOS系统进行组件的渲染;

  • Flutter是自己完成组件的渲染

在计算机系统中,图像的显示需要CPU、GPU和显示器一起配合完成:

  • CPU负责图像数据的计算

  • GPU负责图像数据的渲染

  • 显示器负责最终图像的显示

CPU把计算好的、需要显示的内容交给GPU,由GPU完成渲染后放入帧缓存区,随后由视频控制器根据垂直同步信号(VSync)以每秒60次的速度,从帧缓存区读取帧数据交由显示器完成图像的显示。

操作系统在呈现图像时遵循了这种机制,而Flutter作为跨平台开发框架也采用这种底层方案:

上图中,Flutter 关注如何尽可能快地在两个硬件时钟的 VSync 信号之间计算并合成视图数据,然后通过 Skia 交给 GPU 渲染:UI 线程使用 Dart 来构建视图结构数据,这些数据会在 GPU 线程进行图层合成,随后交给 Skia 引擎加工成 GPU 数据,而这些数据会通过 OpenGL 最终提供给 GPU 渲染。

Skia是一款2D图像绘制引擎,是Android官方图像绘制引擎,因此在Android Flutter中无需嵌入Skia引擎就可以天然得到Skia的支持,而IOS系统中并没有内置Skia引擎,所以Flutter IOS打包的App包体积比Android要大一些。

 

Dart语言作为Flutter的开发语言:

1. Dart同时支持了JIT和AOT两种编译模式,JIT(Just In Time)即时编译,便于在开发期调试;AOT(Ahead Of Time)事前编译,提高程序执行效率。

2. Dart避免了抢占式调度和共享内存,可以在没有锁的情况下进行对象的分配和垃圾回收,在性能上表现相当不错。

 

Flutter原理:

Flutter架构采用分层设计,从下到上分为3层:Embedder、Engine、Framework。

Embeder层是操作系统适配层,实现了渲染Surface设置、线程设置,以及平台插件等平台相关特性的适配。

Engine层主要包括Skia、Dart和Text,实现了Flutter的渲染引擎、文字排版、事件处理和Dart运行的能力。Skia和Text为上层接口提供了调用底层渲染和排版的能力,Dart则为Flutter提供了运行时调用Dart和渲染引擎的能力。Engine层则是将它们组合起来,从它们生成的数据中实现视图渲染。

Framework层是一个用Dart实现的UI SDK,包含了动画、图形绘制和手势识别等功能,在Framework层Flutter提供了Material和Cupertino两种风格的组件库。

 

Flutter工作原理/流程:

Flutter界面中各个元素(Widget)以树的形式组织,即控件树。Flutter通过控件树上的每个控件创建不同类型的渲染对象,组成了渲染对象树。渲染对象树在Flutter的展示过程分为4个阶段:

  • 布局

  • 绘制

  • 合成

  • 渲染

布局:

Flutter采用深度优先策略遍历整个渲染对象树,决定渲染对象在屏幕中的位置和尺寸。在布局过程中每个渲染对象都会接收父对象的布局约束参数,决定自己的大小,父对象按照控件布局逻辑决定每个子对象的位置,完成布局过程。

布局边界:为了防止因子节点发生变化而导致整个控件树重新布局,Flutter引入了机制:布局边界(Relayout Boundary),可以在某些节点上自动或手动设置布局边界,当布局边界内的任何对象发生重新布局的时候,都不会影响边界外的对象,反之边界外的对象发生重新布局,也不会影响边界内的对象。

绘制:

布局完成之后,渲染对象树的每个节点都有了明确的尺寸和位置,Flutter会把所有的渲染对象绘制到不同的图层上。绘制的过程也是采用深度优先策略,而且总是先绘制自身,再绘制子节点。

上图中,节点1在绘制完自身后,会再绘制节点2,然后绘制它的子节点3、4 和 5,最后绘制节点6。由于某些原因(e.g. 视图手动合并)导致节点2的子节点5和它的兄弟节点6处于同一层,这样会导致当节点2需要重绘的时候,与其无关的节点6也会被重绘,带来性能的损耗。

为了解决这一问题,Flutter提供了与布局边界对应的机制-重绘边界(Repaint Boundary)。在重绘边界内,Flutter会强制切换新的图层,避免边界内外的节点相互影响,避免无关内容置于同一层引起不必要的重绘。

重绘边界的一个典型场景是 Scrollview。ScrollView 滚动的时候需要刷新视图内容,从而触发内容重绘。而当滚动内容重绘时,一般情况下其他内容是不需要重绘的,这时候重绘边界就派上用场了。

合成和渲染:

当绘制界面复杂的时候,Flutter的渲染树层级通常会很多,直接交付给渲染引擎进行多图层的渲染,可能会出现大量渲染内容重复绘制,所以还需要进行一次图层合并,即将所有的图层按照大小、层级、透明度等规则计算出最终的显示效果,将相同的图层进行归类合并,简化渲染树,提高渲染引擎的渲染效率。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值