flutter知识体系

image.png

<header class="entry-header" style="box-sizing: inherit; border: 0px; font-family: "Microsoft YaHei", Helvetica, Arial, "Lucida Grande", Tahoma, sans-serif; font-size: 14px; font-style: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; display: block; color: rgb(68, 68, 68); font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

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

</header>

2019年7月12日11:30:20 发表评论 638 views[](javascript:printme() "打印")

跨端方案经历了三个阶段,第一阶段是混合开发的Web容器时代,第二阶段是以RN和Weex为代表的泛Web容器时代,第三阶段就是以Flutter为代表的自绘引擎时代。

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

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

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

那么,Flutter是怎么完成组件渲染的呢?这需要从图像显示的基本原理说起。

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

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

在计算机系统中,图像的显示需要CPU、GPU和显示器一起配合完成:CPU负责图像数据计算,GPU负责图像数据渲染,而显示器则负责最终图像显示。

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

操作系统在呈现图像时遵循了这种机制,而Flutter作为跨平台开发框架也采用了这种底层方案。下面有一张更为详尽的示意图来解释Flutter的绘制原理。

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

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

Skia是什么

Skia是Flutter的底层图像渲染引擎。

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

目前,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要大一些的原因。

底层渲染能力统一了,上层开发接口和功能体验也就随即统一了,开发者再也不用担心平台相关的渲染特性了。也就是说,Skia保证了同一台代码调用在Android和iOS平台上的****渲染****效果是完全一致的

为什么是Dart?

前文提到,Dart因为同时支持JIT和AOT,所以既开发效率高,又运行速度好、执行性能高,那么除了这个特点之外,还有什么特点促使Flutter选择Dart,而不是选择前端应用的准官方语言JavaScript呢?

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

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

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

Dart是一门优秀的现代语言,最初设计也是为了取代JavaScript称为Web开发的官方语言,但竞争结果如此之强,最后结果可想而知。

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

Flutter原理

首先我们来看一下Flutter的架构图:

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

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

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

布局

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

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

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

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

绘制

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

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

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

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

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

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

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

合成和渲染

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

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

小结

Skia和Dart是构建Flutter底层的关键技术,也是Flutter区别于其他跨平台方案的核心所在。

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

最后来一张Flutter的指知识体系导图吧,与君共勉。

Flutter区别其他技术的关键是什么?附Flutter知识体系导图
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容