跨端那些事之Flutter

221 阅读6分钟

我正在参加「掘金·启航计划」

前端跨端那些事之React Native中主要介绍了什么是React Native以及原理,本篇主要讲述自绘+原生开发方式的代表Flutter。

什么是Flutter

Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter 提供了丰富的组件、接口,开发者可以很快地为 Flutter 添加 Native(即原生开发,指基于平台原生语言来开发应用,flutter可以和平台原生语言混合开发) 扩展。下面我们整体介绍一下 Flutter 技术的主要特点。

自绘之跨平台自绘引擎

我们开头提到过Flutter跟RN的区别在于RN采用的是原生渲染而Flutter采用的是自绘的方式。Flutter 既不使用 WebView,也不使用操作系统的原生控件。 相反,Flutter 使用自己的高性能渲染引擎来绘制 Widget(组件)。这样不仅可以保证在 Android 和iOS 上 UI 的一致性,也可以避免对原生控件依赖而带来的限制及高昂的维护成本。

Flutter 底层使用 Skia 作为其 2D 渲染引擎,Skia 是 Google的一个 2D 图形处理函数库,包含字型、坐标转换,以及点阵图,它们都有高效能且简洁的表现。Skia 是跨平台的,并提供了非常友好的 API,目前 Google Chrome浏览器和 Android 均采用 Skia 作为其 2D 绘图引擎。

目前 Flutter 已经支持 iOS、Android、Web、Windows、macOS、Linux、Fuchsia(Google新的自研操作系统)等众多平台

Flutter如何保证高性能

Flutter保证高性能基于两点:

  1. Flutter采用的开发语言是Dart,Dart在即时编译(JIT)模式下的执行速度跟JavaScript基本持平,但是Dart还支持提前编译(AOT),在提前编译模式下的执行速度远远快于JavaScript。对高帧率视图很有帮助。

  2. Flutter的渲染是自己控制的,不是由客户端去渲染。布局的数据直接由Dart去控制,不需要像RN那样因为一些场景导致页面发生变化而需要JavaScript和Native去做一些数据同步,并且频繁的改变DOM。进而节省一些不必要的性能开销。

什么是Dart

Dart 也是 Flutter 的基础。 Dart 作为 Flutter 应用程序的编程语言,为驱动应用运行提供了环境,同时 Dart 还支持许多核心的开发任务,例如格式化,分析和代码测试。

Dart 语言是类型安全的;它使用静态类型检查来确保变量的值 始终 与变量的静态类型相匹配。这也叫健全类型。尽管类型是强制性的,但由于 Dart 支持类型推断,类型注释仍是可选的。 Dart 的类型系统也很灵活,允许结合使用 dynamic 类型与运行时检查,在测试开发期间,或是遇到需要特别指定为动态类型的代码时,这项特性很有帮助。

与其他许多空安全语言不同, Dart 提供 健全的空值安全,这意味着只有您声明值可以为空的情况下,值才可以为空;当 Dart 确定变量不可为空时,该变量 永远 不可为空。凭借健全的空值安全,Dart 可以通过静态代码分析在运行时保护您免受空值异常的影响。如果你在调试器中审查正在运行的代码,你会看到不可为空性仍在运行时被保留 (所以是完全空值安全)。

什么是AOT和JIT

  • 静态编译与动态解释。静态编译的程序在执行前程序会被提前编译为机器码(或中间字节码),通常将这种类型称为AOT (Ahead of time)即 “提前编译”。
  • 解释执行则是在运行时将源码实时翻译为机器码来执行,通常将这种类型称为JIT(Just-in-time)即“即时编译”。

Flutter框架结构

Flutter官方架构图如下:可以简单的分为框架层、引擎层和嵌入层。

image.png

框架层

Flutter Framework,即框架层。这是一个纯 Dart实现的 SDK,它实现了一套基础库,自底向上,我们来简单介绍一下:

  • 底下两层(Foundation 和 Animation、Painting、Gestures)在 Google 的一些视频中被合并为一个dart UI层,对应的是Flutter中的dart:ui包,它是 Flutter Engine 暴露的底层UI库,提供动画、手势及绘制能力。
  • Rendering 层,即渲染层,这一层是一个抽象的布局层,它依赖于 Dart UI 层,渲染层会构建一棵由可渲染对象组成的渲染树,当动态更新这些对象时,渲染树会找出变化的部分,然后更新渲染。渲染层可以说是Flutter 框架层中最核心的部分,它除了确定每个渲染对象的位置、大小之外还要进行坐标变换、绘制(调用底层 dart:ui )。
  • Widgets 层是 Flutter 提供的一套基础组件库,在基础组件库之上,Flutter 还提供了 Material 和 Cupertino 两种视觉风格的组件库,它们分别实现了 Material 和 iOS 设计规范。

我们进行Flutter 开发时,大多数时候都是和 Flutter Framework 打交道。

引擎层

Engine,即引擎层。毫无疑问是 Flutter 的核心, 该层主要是 C++ 实现,其中包括了 Skia 引擎、Dart 运行时(Dart runtime)、文字排版引擎等。在代码调用 dart:ui库时,调用最终会走到引擎层,然后实现真正的绘制和显示。

嵌入层

Embedder,即嵌入层。Flutter 最终渲染、交互是要依赖其所在平台的操作系统 API,嵌入层主要是将 Flutter 引擎 ”安装“ 到特定平台上。嵌入层采用了当前平台的语言编写,例如 Android 使用的是 Java 和 C++, iOS 和 macOS 使用的是 Objective-C 和 Objective-C++,Windows 和 Linux 使用的是 C++。 Flutter 代码可以通过嵌入层,以模块方式集成到现有的应用中,也可以作为应用的主体。Flutter 本身包含了各个常见平台的嵌入层,假如以后 Flutter 要支持新的平台,则需要针对该新的平台编写一个嵌入层。

小结

  1. Flutter基于自绘引擎+原生的方式去开发,因为自有引擎渲染抹平了不同平台的差异,可以保持UI的高度一致性。
  2. Flutter自绘引擎不需要在渲染时和Native频繁通信,在动画和一些拖拽等操作上性能优于RN,更接近于原生的体验。
  3. Dart作为一种新的开发语言,上手难度要高于RN。