Flutter区别其他技术的关键是什么?附Flutter知识体系导图

2019-07-1211:30:20APP与小程序开发Comments3,134 views字数 4149阅读模式

跨端方案经历了三个阶段,第一阶段是混合开发的Web容器时代,第二阶段是以RN和Weex为代表的泛Web容器时代,第三阶段就是以Flutter为代表的自绘引擎时代。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

一开始,为了解决原生开发的高成本、低效率,出现了Hybrid混合开发,也就是在原生中嵌入依托于浏览器的WebView,Web浏览器中可以实现的需求在WebView中基本都可以实现。但是Web最大的问题是,它的性能和体验与原生开发存在肉眼可感知的差异,因此并不适用于对性能和用户体验要求较高的场景。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

后来的RN对Web标准进行了功能裁剪,于是用户体验更接近于原生了,但是由于进行了功能裁剪,所以RN对业务的支持能力还不到浏览器的5%,因此仅适用于中低复杂度的低交互类页面。面对稍微复杂一点儿的交互和动画需求,都需要通过调用原生代码去扩展才能实现。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

再到后来,也就是现在,出现了Flutter。Flutter是构建Google物联网操作系统Fuchsia的SDK,它使用Dart语言开发APP,一套代码可以同时运行在iOS和Android平台上。Flutter采用自带的Native渲染引擎渲染视图,它是自己完成了组件渲染的闭环;而RN、Weex之类的框架,只是通过JavaScript虚拟机扩展调用系统组件,最后是由Android或者iOS系统来完成组件的渲染。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

那么,Flutter是怎么完成组件渲染的呢?这需要从图像显示的基本原理说起。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

我们的显示器的CRT电子枪会按照上图中的方式,从上到下一行行扫描,扫描一行完成之后,显示器上就显示一帧画面,随后电子枪回到初始位置继续下一次扫描。水平扫描时,显示器会发出一个水平同步信号(HSync);而当一帧画面绘制完成之后,电子枪恢复原位,准备下一次扫描之前,显示器会发出一个垂直同步信号(Vsync),显示器以固定的频率刷新,这个刷新率就是Vsync信号产生的频率。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

在计算机系统中,图像的显示需要CPU、GPU和显示器一起配合完成:CPU负责图像数据计算,GPU负责图像数据渲染,而显示器则负责最终图像显示。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

CPU把计算好的需要显示的内容交给GPU,由GPU完成渲染后放入帧缓冲区,随后视频控制器根据垂直同步信号(Vsync)以每秒60次的速度,从帧缓冲区读取帧数据交由显示器完成图像显示文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

操作系统在呈现图像时遵循了这种机制,而Flutter作为跨平台开发框架也采用了这种底层方案。下面有一张更为详尽的示意图来解释Flutter的绘制原理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

可以看到,Flutter关注如何尽可能快地在两个硬件时钟的Vsych之间计算并合成视图数据,然后通过Skia交给GPU渲染:UI线程使用Dart来构建视图结构数据,这些数据会在GPU线程进行图层合成,随后交给Skia引擎加工成GPU数据,而这些数据会通过OpenGL最终提供给GPU渲染文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Skia是什么文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Skia是Flutter的底层图像渲染引擎。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Skia是一款由C++开发的、性能彪悍的2D图像绘制引擎,其前身是一个向量绘图软件。2005年被Google公司收购后,由于其出色的绘制表现被广泛应用在Chrome和Android等核心产品上。Skia在图形转换、文字渲染、位图渲染等方面都表现卓越,并提供了开发者友好的API。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

目前,Skia已然是Android官方的图像渲染引擎了,因此Flutter Android SDK无需内嵌Skia引擎就可以获得天然的Skia支持;而对于iOS平台来说,由于Skia是跨平台的,因此它作为Flutter 的iOS渲染引擎被嵌入到了Flutter iOS SDK中,代替了iOS闭源的Core Graphics/Core Animation/Core Text,这也正是Flutter iOS SDK打包的APP包体积比Android要大一些的原因。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

底层渲染能力统一了,上层开发接口和功能体验也就随即统一了,开发者再也不用担心平台相关的渲染特性了。也就是说,Skia保证了同一台代码调用在Android和iOS平台上的渲染效果是完全一致的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

为什么是Dart?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

前文提到,Dart因为同时支持JIT和AOT,所以既开发效率高,又运行速度好、执行性能高,那么除了这个特点之外,还有什么特点促使Flutter选择Dart,而不是选择前端应用的准官方语言JavaScript呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

很多人说,dart是Flutter推广的一大劣势,毕竟多学一门新语言就多一门障碍。但是Google公司给出了他们的解释:Dart语言开发组就在隔壁,对于Flutter需要的一些语言新特性,能够快速在语法层面落地实现;而如果选择了JavaScript,就必须经过各种委员会和浏览器提供商漫长的决议。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

事实上,Dart确实得到了兄弟团队的紧密支持。2018年2月发布的Dart2.0,2018年12月发布的Dart2.1,2019年2月发布的Dart2.2,2019年5月发布的Dart2.3,每次发布都包含了为Flutter量身定制的诸多改造。当然,Google公司选择Dart作为Flutter的开发语言,我想还有其他更有说服力的理由:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

  1. Dart同时支持即时编译JIT和事前编译AOT。在开发期选择JIT,开发调试异常方便(热重载);在发布期使用AOT,本地代码的执行性能更加高效
  2. Dart作为一门现代化语言,集百家之长,拥有其他编程语言的诸多特性。也正是因为这个原因,实际上Dart的学习成本并不高,因为你总能看到自己熟悉的语言的影子。
  3. Dart避免了抢占式调度和共享内存,可以在没有锁的情况下进行对象分配和垃圾回收,在性能方面表现相当不错。

Dart是一门优秀的现代语言,最初设计也是为了取代JavaScript称为Web开发的官方语言,但竞争结果如此之强,最后结果可想而知。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

而随着Flutter的发布,Dart开始转型,其自身定位也发生了变化,专注于改善构建客户端应用程序的体验,因此越来越多的开发者开始慢慢了解这门语言,并共同完善它的生态。凭借着Flutter的火热势头,辅以Google强大的运作能力,相信转型后的Dart前景会非常光明。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter原理文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

首先我们来看一下Flutter的架构图:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter 架构采用分层设计,从下到上分为三层,依次为:Embedder、Engine和Framework。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

  • Embedder是操作系统适配层,实现了渲染Surface设置,线程设置,以及平台插件等平台相关特性的适配。从这里我们可以看到Flutter平台相关特性并不多,这就使得从框架层面保持跨端一致性的成本相对较低。
  • Engine层主要包含Skia、Dart和Text,实现了Flutter的渲染引擎、文字排版、事件处理和Dart运行时等功能。Skia和Text为上层接口提供了调用底层渲染和排版的能力,Dart则为Flutter提供了运行时调用Dart和渲染引擎的能力。而Engine层的作用,则是将他们组合起来,从他们生成的数据中实现视图渲染。
  • Framework层则是一个用Dart实现的UI SDK,包含了动画、图形绘制和手势识别等功能。为了在绘制控件等固定样式的图形时提供更直观更方便的接口,Flutter还基于这些基本能力,根据Material和Cupertino两种视觉设计风格封装了一套UI组件库。我们在开发Flutter的时候,可以直接使用这些组件库。

布局文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter采用深度优先机制遍历渲染对象树,决定渲染对象树中各渲染对象在屏幕上的位置和尺寸。在布局过程中,渲染对象树中的每个渲染对象都会接收父对象的布局约束参数,决定自己的大小;然后父对象按照控件逻辑决定各个子对象的位置,完成布局过程。如下图所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

为了防止因子节点发生变化而导致整个控件树重新布局,Flutter加入了一个新的机制——布局边界(Relayout Boundary),可以在某些节点自动或手动地设置布局边界,当边界内的任何对象发生重新布局时,不会影响边界外的对象,反之亦然。如下图:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

绘制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

布局完成以后,渲染对象树中的每个节点都有了明确的尺寸和位置。Flutter会把所有的渲染对象,绘制到不同的图层上。与布局过程一样,绘制过程也是深度优先遍历,而且总是先绘制自身,再绘制子节点文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

以下图为例,节点1在绘制完自身后,会再绘制节点2,然后绘制子节点3、4和5,最后绘制节点6。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

可以看到,由于一些其他原因(比如,视图手动合并)导致2的子节点5与它的兄弟节点6处于了同一层,这样会导致当节点2需要重绘的时候,与它无关的节点6也会被重绘,带来性能损耗。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

为了解决这一问题,Flutter提出了与布局边界对应的机制——重绘边界(Repaint Boundary)。在重绘边界内,Flutter会强制切换新的图层,这样就可以避免边界内外的互相影响,避免无关内容置于同一图层引起不必要的重绘。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

重绘边界的一个典型场景是ScrollView。ScrollView滚动的时候需要刷新视图内容,从而触发内容重绘。而当滚动内容重绘时,一般情况下其他内容是不需要重绘的,这时候重绘边界就派上用场了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

合成和渲染文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

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

合并完成后,Flutter会将集合图层数据交由Skia引擎加工成二位图像数据,最终交由GPU进行渲染,完成界面的展示。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

小结文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Skia和Dart是构建Flutter底层的关键技术,也是Flutter区别于其他跨平台方案的核心所在。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

跨平台方案的局限就是真正的多端一致性很难完全保证。RN这种就不用说了,很多组件的表现行为两端都不一样。就连Flutter也只能做到渲染层以上的多端一致性,还有一些原生的东西(比如Push、地图、定位、蓝牙、WebView)绕不开,需要通过在原生上写插件来搞定。不过话说回来,如果真的绕开了,那Flutter就变成操作系统了,打出来的包没个几百兆估计是搞不定的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

最后来一张Flutter的指知识体系导图吧,与君共勉。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

Flutter区别其他技术的关键是什么?附Flutter知识体系导图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/14035.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/14035.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定