flutter渲染框架,flutter渲染引擎

Flutter是一个什么框架

Flutter是一个移动应用程序的软件开发工具包(SDK),具有以下特征:

创新互联公司是网站建设技术企业,为成都企业提供专业的成都网站制作、成都网站设计,网站设计,网站制作,网站改版等技术服务。拥有十载丰富建站经验和众多成功案例,为您定制适合企业的网站。十载品质,值得信赖!

跨平台应用的框架,没有使用WebView或者系统平台自带的控件,使用自身的高性能渲染引擎自绘

简化版的浏览器,最大限度在android和ios上统一UI,包括业务逻辑和用户体验

开发语言使用dart,结合C, C++, 和Skia(2D渲染引擎)构建

支持hot reload,包含着完整的控件和工具链

一切皆控件,控件是每个Flutter应用程序的基本构建块,与分离视图、控制器、布局和其他属性的框架不同,Flutter具有一致的统一对象模型:控件。一个控件可以定义:结构元素(比如按钮或菜单)、风格元素(比如字体或颜色方案)、布局的方面(比如填充)、一些业务逻辑等

组合大于继承,控件本身通常由许多小型、单用途的控件组成,结合起来产生强大的效果,类的层次结构是扁平的,以最大化可能的组合数量

强化版的WebView,框架仅提供一个View层,大部分功能要依赖原生

目前只能够运行大部分Dart代码(不能引入dart:mirrors或dart:html库)

Flutter面试:渲染原理

页面中的各界面元素(Widget)以树的形式组织,即控件树。Flutter通过控件树中的每个控件创建不同类型的渲染对象,组成渲染对象树。而渲染对象树在Flutter的展示过程分为三个阶段:布局、绘制、合成和渲染。

(一)布局

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

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

二)绘制

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

以下图为例:节点1在绘制完自身后,会再绘制节点2,然后绘制它的子节点3、4和5,最后绘制节点6。

可以看到,由于一些其他原因(比如,视图手动合并)导致2的子节点5与它的兄弟节点6处于了同一层,这样会导致当节点2需要重绘的时候,与其无关的节点6也会被重绘,带来性能损耗。

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

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

(三)合成和渲染

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

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

四、总结

咱们从各种业界主流跨端方案与Flutter的对比开始,到Flutter的简要介绍以及Flutter的运行机制,并以界面渲染过程为例,从布局、绘制、合成和渲染三个阶段讲述了Flutter的实现原理。相信大家对Flutter已经有一个整体认知,赶快一起上手操作起来吧!

为什么Flutter开发APP性能最接近原生,前端程序员请关注

Flutter是谷歌公司推出的跨终端的开发框架,支持Android、iOS和WEB终端。1.0版在2018年12月5日发布,目前的最新版本是1.5,它采用的开发语言是Dart,Dart也是谷歌开发的计算机编程语言,语法类似C,是编译型语言:

hello world例子,打印字符串“Hello World!”:

1、没有桥接层

React Native、Weex等技术都是跨终端的框架,然而性能跟原生App存在很大差距。这是由于它们的工作原理决定的:

React Native、Weex等技术多了一个桥接层,所以界面渲染会慢一些,由于UI渲染非常频繁,想要不卡顿,基本上比较难,性能和用户体验跟原生代码有差距。而这恰恰是Flutter的优势所在:

Dart可以被编译成不同平台的本地代码,让Flutter不通过桥接层直接跟平台通信,自然性能会快一些。

2、编译执行

JavaScript是解释执行的,Dart是编译执行的,性能谁好一目了然。

3、Flutter Engine虚拟机

Flutter是依靠Flutter Engine虚拟机在iOS和Android上运行的,Flutter Engine使用C/C++编写,开发人员通过Flutter框架直接和API在内部进行交互,所以具有输入低延迟和UI渲染高帧速率的特点。除了这特点之外,Flutter还提供了自己的小部件,Flutter小部件是使用从React获取灵感的现代框架构建的。 中心思想是您使用小部件构建UI。

窗口小部件根据其当前配置和状态描述了它们的视图。 当窗口小部件的状态发生更改时,窗口小部件会重建其描述,框架将根据前面的描述进行区分,以确定底层呈现树从一个状态转换到下一个状态所需的最小更改。可以直接在OS平台提供的画布上进行描绘,也就是一些核心类库直接放到虚拟机里面,调用起来更快。

从它的系统结构可以看出,类似安卓的ART(Android Run Time)虚拟机,同样采用AOT(Ahead of TIme)技术,会在APP安装时就编译成机器语言,不再解释执行,从而优化了APP运行的性能。

4、自带渲染引擎

Flutter使用谷歌自己的Skia渲染引擎,而Android系统自带Skia引擎,iOS平台上Flutter也会把Skia引擎打包到APP中,从而实现了高效渲染。而React Native通过桥接层访问原生UI,操作频繁就容易出性能问题。

综合所述,Flutter 是性能最接近原生代码 的一种开发框架,未来也会是构建谷歌Fuchsia应用的主要方式,前途不可限量,唯一的问题就是需要学习一门新的语言:Dart,而有Java或者C#语言基础的程序员会比较容易学习。

基于Weex的Flutter项目框架

最近在做的一个项目,项目的前期采用Weex开发。但是随着交互复杂度的增加,Weex一处开发多处多处运行的特征并没有很好的体现,相反很多时候我们还是需要做IOS和Android的适配。如今火热的Flutter相比Weex和Rn来说,给出了更好的跨平台解决方案。所以我们设计了一套基于Weex实现,底层跑在Flutter Engine上的框架。

底层的Runtime采用isolate engine,框架业务逻辑,Dom的解析逻辑和Render逻辑都跑在这里。

渲染引擎采用Flutter的Skia,彻底剥离了Android和IOS的差异性.

将Weex VirsualDom的解析都替换成Flutter Widget.

设计基于Weex2Dart的Brider,使JS和Dart可以相互调用

weex-demo的性能展示

release环境下采用AOT模式,性能会有质的飞跃。

Android-Release版本只有10m大小

相比Weex和Rn具有更好的性能,同时具有更好的跨平台性

相比Flutter,具有动态部署的能力(Flutter Release采用AoT模式并没有动态部署的能力,即使Debug版本也只是开发环境下才有动态化能力并没有可以实施项目的能力)

只需要会Weex开发或则Rn开发就可以,不需要额外学习Dart,已有的Weex项目可以无缝切换。

三、Flutter的渲染机制之RenderObjectWidget、RenderObjectElement、RenderObject

RenderObjectWidget 是 Widget 例如 SizeBox , Column 等

RenderObjectElement 是这类 Widget 生成的 Element 类型,

例如 SizeBox 对应 SingleChildRenderObjectElement (单子节点的 Element )

RenderObject 才是真正负责绘制的对象,其中包含了 paint , layout 等方法~

Text 组件为例:

class Text extends StatelessWidget

Text build返回的是

class RichText extends MultiChildRenderObjectWidget

MultiChildRenderObjectWidget - MultiChildRenderObjectElement

RenderObjectElement 会重写 mount

遍历 _parent (就是上个节点的 element ,这个 _parent 在每次的 mount 方法设置),一直遍历知道找到最近的一个 RenderObjectElement

在回顾下 inflateWidget

SingleChildRenderObjectElement

MultiChildRenderObjectElement

inflateWidget 会触发 RenderObjectWidget 的 createElement 创建 RenderObjectElement ,

再调用 RenderObjectElement 的 mount 方法

mount 方法调用 RenderObjectWidget 的 createRenderObject 方法创建 RenderObject

然后找到最近的一个父 RenderObjectElement 调用 insertRenderObjectChild 插入 RenderObject

(注意:这里不是 RenderObjectElement 的 child ,而是 RenderObjectElement 关联的 RenderObject 的 child , element 树里面都是 element , RenderObject 树里面都是 RenderObject )

MultiChildRenderObjectElement 多子节点挂载逻辑

多节点添加子节点逻辑

每个子节点的 parentData 的 after 用来指向前一个子节点 previous 指向下一个子节点


分享题目:flutter渲染框架,flutter渲染引擎
文章网址:http://myzitong.com/article/dssipes.html