## 一、移动跨平台技术趋势
### 1. 引言
移动互联网发展十余年,伴随着 Android、iOS 等智能手机的不断普及,移动端已逐步取代 PC 端,成为兵家必争之地。正所谓“得移动端者得天下”,移动端已成为互联网领域最大的流量分发入口,一大批互联网公司正是在这大趋势下崛起。
### 2. 为什么需要跨平台技术
伴随着移动互联网的高速发展,公司间竞争越来越激烈,如何将好想法快速落地、快速试错,成为备受关注的问题。提升研发效率、缩短研发周期,保障产品快速试错并能快速迭代新功能,让新产品新功能以最快的速度同时抵达 Android、iOS 等多端用户。
众所周知,Android 应用采用 Java 或 Kotlin 编写,iOS 应用采用 Objective-C 或 Swift 编写,Web 端采用 HTML /CSS/JavaScript 编写。当需要开发支持多端的应用,每一端都需要独立研发、测试,一直到上线,以及后续的维护工作,工作量成倍增涨,势必延长研发周期。
为了解决多端独立开发的问题,跨平台技术便应运而生,各大互联网公司为此都投入大量人力,于是出现了各种跨平台技术框架,**面对移动领域的跨平台技术方案的层出不穷,又该如何做技术选型呢?**
### 3. 移动端技术选型
作为移动端的跨端技术方案,所关注无外乎以下这 4 个方面:研发效率、动态性、多端一致性、性能体验。

- **研发效率**:最大化代码复用,减少多端差异的适配工作量,降低开发成本,专注业务开发,实现 “write once,run everywhere” 的终极目标。效率提升是贯穿整个业务的生命周期线,即便业务上线后,可持续降低后续的维护成本,加快新 feature 的迭代速度,这是一个持续的效率收益。当然,这里不得不说,任何一门新技术在开发启动学习阶段会有一些成本,但上手后的收益是长期的。
- **动态化**:突破渠道的更新频率,可快速迭代新功能,这一点不仅是跨平台技术的诉求,也是 Native 技术必备的杀手锏,这也是评估跨端技术的一个重要考核点。
- **多端一致性**:好产品在多端 UI 设计上,往往是整体风格统一,所以业务方采用原生各自独立开发完成后,还需额外花不少时间来修改 UI 以保证多端一致性;可见,各端独立实现开发方式,带来的效率滞后,不仅仅是 Android 和 iOS 各开发一份代码的工作量,还有双端 UI 的一致性对齐的工作。
- **性能体验**:一般来说,跨端技术方案拥有以上多重优势,但在性能方面比原生流畅性要差些。牺牲部分体验换来效率提升,这一点也是情理之中,试想一下,如果跨平台技术方案同时兼得这 4 点,那么原生技术恐怕已退出历史舞台,早已是跨平台技术的天下,所以往往跨平台技术的性能优劣便成为核心指标。
### 4. 跨平台技术划分
对研发效率和体验的不断追逐,移动端的跨平台技术方框架层出不穷,然则天下武功众多,万变不离其宗,从其核心本质来划分,可大致分为以下三大类:

- **Web 技术**:主要依赖于 WebView 的技术,功能支持受限,性能体验很差,比如:PhoneGap、Cordova、小程序。
- **原生渲染**:使用 JavaScript 作为编程语言,通过中间层转化为原生控件来渲染 UI 界面,比如:React Native、Weex。
- **自渲染技术**:自行实现一套渲染框架,可通过调用 Skia 等方式完成自渲染,而不依赖于原生控件,比如:Flutter、Unity。
### 5. 跨平台技术演进
跨平台技术,一直以来是每一个有追求的开发者所追逐的梦想,同时也是守旧者的噩梦,跨平台的多端一体化方案势必颠覆现有的原生各端独立开发模式,接下来列举众多的跨平台技术中最为关键的几个技术方案的演进阶段。

从上图可以看出,技术演进过程大致分以下三个阶段:
第一阶段,采用 WebView 技术绘制界面的 Hybrid 混合开发技术,通过 JS Bridge 将系统部分能力暴露给 JS 调用,其缺点是性能较差,功能受限,扩展性差,不适合交互复杂的场景,比如:Cordova。
第二阶段,针对 WebView 界面性能等问题,于是绘制交还原生渲染,仅仅通过 JS 调用原生控件,相比 WebView 技术性能体验更好,这是目前绝大部分跨平台框架的设计思路,比如:React Native、Weex。另外,最近小程序也比较火,第一阶段和第二阶段的融合,依然采用 WebView 作为渲染容器,通过限制 Web 技术栈的子集,规范化组件使用,并逐步引入原生控件代表 WebView 渲染,以提升性能。
第三阶段,虽然通过桥接技术使用原生控件解决了功能受限问题,提升性能体验,但相比原生体验差距还是比较大,以及处理平台差异性非常耗费人力。于是 Flutter 提出自带渲染引擎的解决方案,尽可能减少不同平台间的差异性, 同时媲美原生的高性能体验,因此业界对 Flutter有着极高的关注度。
**面对现有的如此多跨平台方案,为何当下最火的跨平台技术是 Flutter,有哪些优势呢?**
React Native、Weex 均使用 JavaScript 作为编程语言,JavaScript 作为前端开发语言,在跨平台开发中可谓大放异彩,利用 Web 技术不仅能开发出网站,也可以开发手机端 Web 应用和移动端应用程序,似有一统三界(Android、iOS、Web)的趋势,这就是大家常说的 “大前端” 时代。这些技术方案流畅度不太好,平台一致性较差,至今还没能大面积取代原生开发。
Flutter 是使用 Dart 作为编写语言,开发体验更接近客户端,从大家使用反馈来看也是如此,Flutter 开发环境这一套的流程对于前端开发来说并不太友好。Flutter 的定位同样是多端一体化,但是以客户端为首,先磨平 Android 和 iOS 双端开发体验,再逐步向 Web 端渗透,从 Flutter 规划的 Roadmap 也能看出,Flutter for Web 目前仍处于预览版,Flutter 客户端方向都已经如火如荼上线了不少应用。
在此之前,大家常说的 “大前端”,对于 Flutter 技术,在笔者看来称之为 “大移动端” 更贴切,Flutter 的 UI 框架优先支持客户端(Android/iOS)应用的同时,然后再适配 Web 端。移动互联网时代,不少公司都制定 “移动优先” 的战略,甚至只开发移动端,没有 Web 端。移动互联网的时代造就了 “大移动端”,Flutter 作为一款能做到媲美原生的高性能跨平台技术方案,或许能一统天下。
在跨平台技术领域,只要挑战在,技术就不会停滞,伴随着技术不断演进与革新,终将走向美好。
## 二、 Flutter 技术优势
Flutter 是彻底的跨平台方案,既没有采用 WebView,也没有采用 JS 桥接原生控件,而是自行实现一套 UI 框架,在引擎底层通过 Skia 渲染到屏幕。对于 UI 之外所需要使用的移动设备自身提供的服务,比如:相机、定位、屏幕触摸等,则采用 Platform Channels 跟原生系统通信的方式来实现。
对于 Flutter 优势,回到前面讲到移动端技术选型的 4 要素:研发效率、动态性、多端一致性、性能体验,分别对应下面这一组词语:

- **高效率**:采用 Dart 语言编写代码,虽然刚开始上手需要点时间,但熟练后效率比较高。一套代码适用多个平台(Android、iOS、Web),以及高效的 Hot Reload 能快速辅助调试。
- **动态化**:2017年3月苹果下发警告邮件,禁止 JSPatch 等 iOS App 热更新方案,从此 iOS 动态化成为一个不宜公开讨论的话题。同样地, Flutter 引擎在某一个官方版本对动态化做过一些尝试,但后续基于风险考虑移除,当然并没有阻碍大家对技术的探索,这里不方便展开讨论。
- **高一致性**:实现 UI 像素级的控制,Flutter 渲染引擎依靠跨平台 Skia 图形库来实现,仅依赖系统图形绘制相关的接口,比如未来 Android 会支持 vulkan,iOS 会支持 metal,这些都是通过 Skia 封装调用。可最大程度上保证不同平台的体验一致性,见下图所示:

- **高性能**:渲染性能优于现有的各种跨平台框架,可媲美原生性能的跨平台技术方案,Dart 代码执行效率比 JS 高,通过 AOT 编译成平台原生代码,渲染采用自渲染 Skia 方案,既不需要 JS Bridge 桥接,也不需要 Art 虚拟机参与。再从渲染原理来看看 Flutter 的高性能的底气在哪里,见下图所示:

图解:
- Android 原生框架,通过调用 Java Framework 层,再调用到 Skia 来渲染界面。
- 其他跨平台方案(如:React Native),通过 JSBridge 中间层来将 JS 写的 App 转换成相应的原生渲染逻辑,可见比 Native 代码增加了更多逻辑,性能逊色差于原生框架。
- Flutter 框架,App 通过调用 Dart Framework 层,再直接调用到 Skia 来渲染界面,并没有经过原生 Framework 过程,可见其渲染性能并不会弱于 Native 技术,这是一个性能上限很高的跨平台技术。
当然,不得不说目前的 Flutter 确实不够尽善尽美,会存在一些不够尽善尽美之处,比如生态不够健全,包体积问题,但其该方案的上限比较高,想象空间比较大,相信更多开发者参与进来,经过更多打磨,未来会做得更好。
## 三、Flutter 业界发展近况
2017年5月 Google I/O 大会正式对外公布 Flutter,到2018年12月发布 Flutter 1.0 版本,引发全球大量的开发者和企业开始研究 Flutter。StackOverflow 2019年的全球开发者文件调查中,Flutter 被评选为最受开发者欢迎的框架之一,超过了 TensorFlow 和 Node.js,见下图所示:

到目前,全球越来越多的公司已经在大家耳熟能详的知名 App 中使用 Flutter 技术并落地,尤其国内知名互联网公司对 Flutter 投入度很大,社区也是非常活跃,见下图所示:

## 四、Flutter 未来趋势
目前 Flutter 主要在移动端 Android/iOS 双端跨端,Flutter 的愿景是成为一个多端运行的 UI 框架,能够支持不仅仅是移动端,还包括 Web、桌面、甚至嵌入式设备。在2019 Google I/O 开发者大会上推出的使用 Flutter 开发 Web 应用的框架,同年9月发布 Flutter 1.9 版本,并将 Flutter Web 合入 Flutter 主仓库。

从架构图看,Flutter 采用同一个 Dart Framework 层来统一 Flutter C++ 引擎和 Web 引擎,最终可以运行在 Android、iOS、Browser 上,从 Flutter 引擎代码不难看出 Flutter 也是支持 Fuchsia 操作系统。
Fuchsia 是 Google 内部正在开发的一款新的操作系统,采用 Flutter 作为系统默认的 UI 框架,也就是说 Flutter 天然支持 Fuchsia,这无疑让 Flutter 在众多的跨平台方案更有优势。
从 Fuchsia 技术架构来看,内核层 zircon 的基础 LK 是专为嵌入式应用中小型系统设计的内核,代码简洁,适合嵌入式设备和高性能设备,比如:IOT、移动可穿戴设备等,目前这些领域还没有标准化级别的垄断者。以及在框架层中有着语音交互、云端以及智能化等模块,由此笔者揣测未来 Fuchsia 率先应用在音控等智能嵌入式设备。

## 五、Flutter 引擎架构
### 1. Flutter 技术架构
先来看看 Flutter 整体的技术架构,分为四层,从上之下依次是 Dart APP,Dart Framework, C++ Engine,Platform。

Flutter 架构最核心的便是 Framework(框架)和 Engine(引擎):
- Flutter Framework 层:用 Dart 编写,封装整个 Flutter 架构的核心功能,包括 Widget、动画、绘制、手势等功能,有 Material(Android风格)的 UI 界面和 Cupertino(iOS风格)的 UI 界面, 可构建 Widget 控件以及实现 UI 布局。
- Flutter Engine层:用C++编写,用于高质量移动应用的轻量级运行时环境,实现了Flutter的核心库,包括Dart虚拟机、动画和图形、文字渲染、通信通道、事件通知、插件架构等。引擎渲染采用的是2D图形渲染库Skia,虚拟机采用的是面向对象语言Dart VM,并将它们托管到Flutter的嵌入层。shell实现了平台相关的代码,比如跟屏幕键盘IME和系统应用生命周期事件的交互。不同平台有不同的shell,比如Android和iOS的shell。
### 2. Flutter 编译产物
看完 Flutter 内部架构,或许你好奇,Flutter 不用 Android/iOS 的本地语言技术开发,Dart 编写完的代码如何让不同系统可以识别,最终编译后得到的产物是什么呢?

Flutter 产物分为 Dart 业务代码和 Engine 代码各自生成的产物,图中的 Dart Code 包含开发者编写的业务代码,Engine Code 是引擎代码,如果并没有定制化引擎,则无需重新编译引擎代码。
一份 Dart 代码,可编译生成双端产物,实现跨平台的能力。经过编译工具处理后可生成双端产物,图中便是 release 模式的编译产物,Android 产物是由 vm、isolate 各自的指令段和数据段以及 flutter.jar 组成的 app.apk,iOS 产物是由 App.framework 和 Flutter.framework 组成的 Runner.app。
这个过程涉及 frontend_server、gen_snapshot、xcrun、ninja 编译工具。frontend_server 前端编译器会进行词法分析、语法分析以及相关全局转换等工作,将 Dart 代码转换为 AST(抽象语法树),并生成 app.dill 格式的 dart kernel。gen_snapshot 经过 CHA、内联等一系列执行流的优化,根据中间代码生成优化后的 FlowGraph 对象,再转换为具体相应系统架构(arm/arm64等)的二进制指令。
### 3. Flutter 引擎启动
既然了解了 Flutter 的编译产物,那你或许又好奇,Flutter 这台引擎如何发动的,怎么跟 Native 衔接呢?

这里以 Android 为例,熟悉 Android 的开发者,应该都了解 App 的启动过程,会执行 Application 和 Activity 的 onCreate() 方法,FlutterApplication 和 FlutterActivity 的 onCreate() 方法正是连接 Native 和 Flutter 的枢纽。
- FlutterApplication.java 的 onCreate 过程主要完成初始化配置、加载引擎 libflutter.so、注册 JNI 方法。
- FlutterActivity.java 的 onCreate 过程,通过 FlutterJNI 的 AttachJNI() 方法来初始化引擎 Engine、Dart 虚拟机、Isolate、taskRunner 等对象。再经过层层处理最终调用 main.dart 中 main() 方法,执行 runApp(Widget app) 来处理整个 Dart 业务代码。
Flutter 引擎启动中会创建有 4 个 TaskRunner 以及创建虚拟机,分别来看看它们的工作原理。
### 4. TaskRunner 工作原理
Flutter 引擎启动过程,会创建 UI/GPU/IO 这 3 个线程,会为这些线程依次创建 MessageLoop 对象,启动后处于 epoll_wait 等待状态。对于 Flutter 的消息机制跟 Android 原生的消息机制有很多相似之处,都有消息(或者任务)、消息队列(或任务队列)以及 Looper;有一点不同的是 Android 有一个 Handler 类,用于发送消息以及执行回调方法,相对应 Flutter 中有着相近功能的便是 TaskRunner。

上图是从源码中提炼而来的任务处理流程,比官方流程图更容易理解一些复杂流程的时序问题,后续会专门讲解个中原由。Flutter 的任务队列处理机制跟 Android 的消息队列处理相通,只不过 Flutter 分为 Task 和 MicroTask 两种类型,引擎和 Dart 虚拟机的事件以及 Future 都属于 Task,Dart 层执行 scheduleMicrotask() 所产生的属于 Microtask。
每次 Flutter 引擎在消费任务时调用 FlushTasks() 方法,遍历整个延迟任务队列 delayed_tasks_,将已到期的任务加入 task 队列,然后开始处理任务。
- Step 1: 检查 Task,当 Task 队列不为空,先执行一个 Task;
- Step 2: 检查 MicroTask,当 MicroTask 不为空,则执行 MicroTask;不断循环 Step 2 直到 MicroTask 队列为空,再回到执行 Step 1;
可简单理解为先处理完所有的 Microtask,然后再处理 Task。因为 scheduleMicrotask() 方法的调用自身就处于一个 Task,执行完当前的 Task,也就意味着马上执行该 Microtask。
了解了其工作机制,再来看看这 4 个 Task Runner 的具体工作内容:
- Platform Task Runner:运行在 Android 或者 iOS 的主线程,尽管阻塞该线程并不会影响 Flutter 渲染管道,平台线程建议不要执行耗时操作;否则可能触发 watchdog 来结束该应用。比如 Android、iOS 都是使用平台线程来传递用户输入事件,一旦平台线程被阻塞则会引起手势事件丢失。
- UI Task Runner: 运行在 UI 线程,比如 1.ui,用于引擎执行 root isolate 中的所有 Dart 代码,执行渲染与处理 Vsync 信号,将 widget 转换生成 Layer Tree。除了渲染之外,还有处理 Native Plugins 消息、Timers、Microtasks 等工作;
- GPU Task Runner:运行在 GPU 线程,比如 1.gpu,用于将 Layer Tree 转换为具体 GPU 指令,执行设备 GPU 相关的 Skia 调用,转换相应平台的绘制方式,比如 OpenGL, vulkan, metal 等。每一帧的绘制需要 UI Runner 和 GPU Runner 配合完成,任何一个环节延迟都可能导致掉帧;
- IO Task Runner:运行在 IO 线程,比如 1.io,前 3 个 Task Runner 都不允许执行耗时操作,该 Runner 用于将图片从磁盘读取出来,解压转换为 GPU 可识别的格式后,再上传给 GPU 线程。为了能访问 GPU,IO Runner 跟 GPU Runner 的 Context 在同一个 ShareGroup。比如 ui.image 通过异步调用让 IO Runner 来异步加载图片,该线程不能执行其他耗时操作,否则可能会影响图片加载的性能。
### 5. Dart 虚拟机工作原理
Flutter 引擎启动会创建 Dart 虚拟机以及 Root Isolate。DartVM 自身也拥有自己的 Isolate,完全由虚拟机自己管理的,Flutter 引擎也无法直接访问。Dart 的 UI 相关操作,是由 Root Isolate 通过 Dart 的 C++ 调用,或者是发送消息通知的方式,将 UI 渲染相关的任务提交到 UIRunner 执行,这样就可以跟 Flutter 引擎相关模块进行交互。
何为 Isolate,从字面上理解是 “隔离”,Isolate 之间是逻辑隔离的。Isolate 中的代码也是按顺序执行,因为 Dart 没有共享内存的并发,没有竞争的可能性,故不需要加锁,也没有死锁风险。对于 Dart 程序的并发则需要依赖多个 Isolate 来实现。

图解:
- isolate 堆是运该 isolate 中代码分配的所有对象的 GC 管理的内存存储;
- vm isolate 是一个伪 isolate,里面包含不可变对象,比如 null,true,false;
- isolate 堆能引用 vm isolate 堆中的对象,但 vm isolate 不能引用 isolate 堆;
- isolate 彼此之间不能相互引用;
- 每个 isolate 都有一个执行 Dart 代码的 Mutator thread,一个处理虚拟机内部任务(比如 GC, JIT 等)的 helper thread; 可见,isolate 是拥有内存堆和控制线程,虚拟机中可以有很多 isolate,但彼此之间内存不共享,无法直接访问,只能通过 Dart 特有的 Port 端口通信;isolate 除了拥有一个 mutator 控制线程,还有一些其他辅助线程,比如后台 JIT 编译线程、GC 清理/并发标记线程;
### 6. Widget 架构概览
Flutter 引擎启动后执行 Dart 业务,是通过 runApp(Widget app) 方法,那 Widget 又是什么呢?

Widget 是所有 Flutter 应用程序的基石,Widget 可以是一个按钮,一种字体或者颜色,一个布局属性等,在 Flutter 的 UI 世界可谓是 “万物皆Widget”。常见的 Widget 子类为 StatelessWidget 和 StatefulWidget:
- **StatelessWidget**:内部没有保存状态,UI 界面创建后不会发生改变;
- **StatefulWidget**:内部有保存状态,当状态发生改变,调用 setState() 方法会触发 StatefulWidget 的 UI 发生更新,对于自定义继承自 StatefulWidget 的子类,必须要重写 createState() 方法。
**三棵树**:

图解:
- Widget 是为 Element 描述需要的配置,负责创建 Element,决定 Element 是否需要更新。Flutter Framework 通过差分算法比对 Widget 树前后的变化,决定 Element 的 State 是否改变。当重建 Widget 树后并未发生改变,则 Element 不会触发重绘,则就是 Widget 树的重建并不一定会触发 Element 树的重建。
- Element 表示 Widget 配置树的特定位置的一个实例,同时持有 Widget 和 RenderObject,负责管理 Widget 配置和 RenderObject 渲染。Element 状态由 Flutter Framework 管理, 开发人员只需更改 Widget 即可。
- RenderObject 表示渲染树的一个对象,负责真正的渲染工作,比如测量大小、位置、绘制等都由 RenderObject 完成。
可见,开发者通过 Widget 配置,Framework 通过比对 Widget 配置来更新 Element,最后调度 RenderObject Tree 完成布局排列和绘制。
### 7. 渲染原理
Dart 的 UI 采用 Widget 来实现,最终转换为 RenderObject,那界面又是如何渲染的呢?

渲染过程,UI 线程完成布局、绘制操作,生成 Layer Tree;GPU 线程执行合成并光栅化后交给 GPU 来处理,其中几个关键步骤:
- Animate: 遍历 _transientCallbacks,执行动画回调方法;
- Build: 对于 dirty 的元素会执行 build 构造,没有 dirty 元素则不会执行,对应于 buildScope();
- Layout: 计算渲染对象的大小和位置,对应于 flushLayout(),这个过程可能会嵌套再调用 build 操作;
- Compositing bits: 更新具有脏合成位的任何渲染对象, 对应于 flushCompositingBits();
- Paint: 将绘制命令记录到 Layer, 对应于 flushPaint();
- Compositing: 将 Compositing bits 发送给 GPU, 对应于 compositeFrame();
GPU 线程通过 Skia 向 GPU 硬件绘制一帧的数据,GPU 将帧信息保存到 FrameBuffer 里面,然后视频控制器会根据 VSync 信号从 FrameBuffer 取帧数据传递给显示器,从而显示出最终的画面。
### 8. Platform Channels
Flutter 框架提供了 UI 的控件支持,对于 App 除了 UI 还有其他依赖于 Native 平台的支持,比如调用 Camera 的功能,该怎么办呢?为此,Flutter 通过提供 Platform Channel 的功能,使得 Dart 代码具备与 Native 交互的能力。

Platform Channel 用于 Flutter 与 Native 之间的消息传递,整个过程的消息与响应是异步执行,不会阻塞用户界面。Flutter 引擎框架已完成桥接的通道,这样开发者只需在 Native 层编写定制的 Android/iOS 代码,即可在 Dart 代码中直接调用,这也就是 Flutter Plugin 插件的一种形式。
## 六、Flutter 源码解读
### 启动篇
- [深入理解 Flutter 引擎启动](http://gityuan.com/2019/06/22/flutter_booting)
- [深入理解 Dart 虚拟机启动](http://gityuan.com/2019/06/23/dart-vm)
- [深入理解 Flutter 应用启动](http://gityuan.com/2019/06/29/flutter_run_app)
### 通信篇
- [深入理解 Flutter 消息机制](http://gityuan.com/2019/07/20/flutter_message_loop)
- [深入理解 Flutter 的 Platform Channel 机制](http://gityuan.com/2019/08/10/flutter_channel)
- [深入理解 Flutter 异步 Future 机制](http://gityuan.com/2019/07/21/flutter_future)
- [深入理解 Flutter 的 Isolate 创建过程](http://gityuan.com/2019/07/27/flutter-isolate)
### 渲染篇
- [Flutter 渲染机制 UI 线程](http://gityuan.com/2019/06/15/flutter_ui_draw)
- [Flutter渲染机制 GPU 线程](http://gityuan.com/2019/06/16/flutter_gpu_draw)
- [深入理解 setState 更新机制](http://gityuan.com/2019/07/06/flutter_set_state)
- [深入理解 Flutter 动画原理](http://gityuan.com/2019/07/13/flutter_animator)
## 七、总结
本文全方位逐级深入的分析 Flutter 技术,先讲述跨平台技术的过去与未来,再解读 Flutter 架构设计原理,最后剖析 Flutter 内部源码,后续将持续更新更多剖析技术深度细节以及实战经验,以彻底揭秘更多 Flutter 技术。
科技不断在进步,技术不断发展,移动跨平台技术几乎从 Android、iOS 诞生不久便出现,已发展快 10 年。时至今日,兼具跨端高效率与高性能体验的 Flutter 力压群雄,崭露头角,已然成为当下最热门的移动端新技术,全球越来越多的公司在 Flutter 技术布局并落地产品应用,社区也非常活跃。
随着 5G+IOT 时代的到来,Fuchsia 系统或许发力 IOT 新战场,你所掌握的 Flutter 技术栈可以无缝迁移,这是一次弯道超车的机会。即便 Fuchsia 落败,相信只要深扎 Flutter 系统技术的精髓,其他任何的移动端新技术都可以轻松快速地掌握。
最后,用一句话来结束本次分享,“有时候,你选择一个方向,不是因为它一定会成为未来,而是它有可能成为不一样的未来。”
原文出自:[http://gityuan.com/flutter](http://gityuan.com/flutter)
非常感谢 [gityuan](http://gityuan.com) 的分享,谢谢!

Flutter 跨平台架构详解