前言

为什么我们需要跨平台开发?本质上,跨平台开发是为了增加代码复用,减少开发者对多个平台差异适配的工作量,降低开发成本,提高业务专注的同时,提供比web更好的体验。通俗了说就是:省钱、偷懒、体验。

跨平台开发方案的三个时代

1 Web 容器时代
基于 Web 相关技术通过浏览器组件来实现界面及功能,典型的框架包括 Cordova(PhoneGap)、Ionic 和微信小程序(WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS脚本)。Web 时代的方案,主要采用的是原生应用内嵌浏览器控件 WebView 的方式进行 HTML5 页面渲染。

由于采用了 Web 开发技术,社区和资源非常丰富,开发效率也很高。但是,一个完整 HTML5 页面的展示要经历浏览器控件的加载、解析和渲染三大过程,性能消耗要比原生开发增加 N 个数量级

2 泛 Web 容器时代
采用类 Web 标准进行开发,但在运行时把绘制和渲染交由原生系统接管的技术,代表框架有 React Native、Weex 和快应用,广义的还包括天猫的 Virtual View 等。
采用原生自带的 UI 组件实现代替了核心的渲染引擎,仅保持必要的基本控件渲染能力,从而使得渲染过程更加简化,也保证了良好的渲染性能。
image
这也是现在绝大部分跨平台框架的思路,而 React Native 和 Weex 就是其中的佼佼者。总结起来其实就是利用 JS 来调用 Native 端的组件,从而实现相应的功能。

3 自绘引擎时代
自带渲染引擎,客户端仅提供一块画布即可获得从业务逻辑到功能呈现的多端高度一致的渲染体验。Flutter,是为数不多的代表。

这一时期的代表 Flutter 开辟了一种全新的思路,即从头到尾重写一套跨平台的 UI 框架,包括渲染逻辑,甚至是开发语言。

渲染引擎依靠跨平台的 Skia 图形库来实现,Skia 引擎会将使用 Dart 构建的抽象的视图结构数据加工成 GPU 数据,交由 OpenGL 最终提供给 GPU 渲染,至此完成渲染闭环,因此可以在最大程度上保证一款应用在不同平台、不同设备上的体验一致性。

而开发语言选用的是同时支持 JIT(Just-in-Time,即时编译)和 AOT(Ahead-of-Time,预编译)的 Dart,不仅保证了开发效率,更提升了执行效率(比使用 JavaScript 开发的泛 Web 容器方案要高得多)。

对比

Ionic、phonegap和Uni-App

给H5加个壳,赋予一些其他的能力 基于WebView(Android下是WebView,iOS下是WKWebView)控件加载H5页面,同时通过框架预先实现的一些能力,实现对设备摄像头、文件系统等设备能力的调用。

react native

react native 利用 JS 通过JavaScriptCore来调用 Native 端的模块(如网络请求,视图控件),从而实现相应的功能, 用了 react 的设计模式,但UI渲染、动画效果、网络请求等均由原生端实现。开发者编写的js代码,通过 react native 的中间层转化为原生控件和操作(DSL),比ionic等跨平台应用,大大提高了的用户体验。

和前端开发不同,react native 所有的标签都不是真实控件,JS代码中所写控件的作用,类似 Map 中的 key 值。JS端通过这个 key 组合的 Dom ,最后Native端会解析这个 Dom ,得到对应的Native控件渲染,如 Android 中<view> 标签对应 ViewGroup 控件。

在 react native 中,JS端是运行在独立的线程中(称为JS Thread )。JS Thread 作为单线程逻辑,不可能处理耗时的操作。那么如 fetch图片加载数据持久化 等操作,在 Android 中实际对应的是 okhttpFrescoSharedPreferences等。而跨线程通信,也意味着 Js Thread 和原生之间交互与通讯是异步的。

WEEX

写个 vue 前端,顺便帮你编译成性能还不错的 apk 和 ipa基于 Vue 设计模式,支持 web、android、ios 三端,原生端同样通过中间层转化,将控件和操作转化为原生逻辑来提高用户体验
在 weex 中,主要包括三大部分:JS BridgeRenderDom;三部分通过WXSDKManager统一管理; JS Bridge 主要用来和 JS 端实现进行双向通信,比如把 JS 端的 dom 结构传递给 Dom 线程。Dom 主要是用于负责 dom 的解析、映射、添加等等的操作,最后通知UI线程更新。而 Render 负责在UI线程中对 dom 实现渲染。

和 react native一样,weex 所有的标签也不是真实控件,JS 代码中所生成存的 dom,最后都是由 Native 端解析,再得到对应的Native控件渲染,如 Android 中 <text> 标签对应 WXTextView 控件。

weex 中文件默认为 .vue ,而 vue 文件是被无法直接运行的,所以 vue 会被编译成 .js 格式的文件,Weex SDK会负责加载渲染这个js文件。Weex可以做到跨三端的原理在于:在开发过程中,代码模式、编译过程、模板组件、数据绑定、生命周期等上层语法是一致的。不同的是在 JS Framework 层的最后,web 平台和 Native 平台,对 Virtual DOM 执行不通的解析.

流程:

  • weex 接收到 js 文件以后,JS Framework 根据文件为 Vue 模式,会调用weex-vue-framework 中提供的 createInstance方法创建实例。(也可能是Rax模式)
  • createInstance 中会执行 Js Entry 代码里 new Vue() 创建一个组件,通过其 render 函数创建出 Virtual DOM 节点。
  • 由JS V8 引擎上解析 Virtual DOM ,得到 Json 数据发送至 Dom 线,这里输出 Json 也是方便跨端的数据传输。
  • Dom 线程解析 Json 数据,得到对应的 WxDomObject,然后创建对应的WxComponent 提交 Render 。
  • Render在原生端最终处理处理渲染任务,并回调里JS方法。

weex 比起react native,主要是在JS V8的引擎上,多了 JS Framework 承当了重要的职责,使得上层具备统一性,可以支持跨三个平台。总的来说它主要负责是:管理Weex的生命周期解析JS Bundle,转为Virtual DOM,再通过所在平台不同的API方法,构建页面进行双向的数据交互和响应

Flutter

Flutter 是一个软件开发工具包(SDK)。它包含众多小部件、框架和工具,能帮助开发者无缝构建跨平台应用

背景
Web 最大的问题在于它的性能和体验与原生开发存在肉眼可感知的差异,因此并不适用于对体验要求较高的场景。

对于用户体验更接近于原生的 React Native,对业务的支持能力却还不到浏览器的 5%,仅适用于中低复杂度的低交互类页面。面对稍微复杂一点儿的交互和动画需求,开发者都需要 case by case 地去 review,甚至还可能要通过原生代码去扩展才能实现。

Flutter 是构建 Google 物联网操作系统 Fuchsia 的 SDK,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码可以同时运行在 iOS 和 Android 平台。Flutter 使用 Native 引擎渲染视图,并提供了丰富的组件和接口

渲染流程:
image
渲染流程

Skia
Skia是一个开源的 2D 图形库,提供各种常用的API,并可在多种软硬件平台上运行。谷歌Chrome浏览器、Chrome OS、安卓、Flutter、火狐浏览器、火狐操作系统以及其它许多产品都使用它作为图形引擎。

Skia 在图形转换、文字渲染、位图渲染方面都表现卓越,并提供了开发者友好的 API。

因此,架构于 Skia 之上的 Flutter,也因此拥有了彻底的跨平台渲染能力。通过与 Skia 的深度定制及优化,Flutter 可以最大限度地抹平平台差异,提高渲染效率与性能。

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

同样的在界面渲染、绘制的过程中,Flutter也做了很多优化处理,提升合成、渲染效率。

Flutter 的优势
  • Google亲儿子
  • for Web
  • 在所有的平台下,都可以保持同样UI样式,同样的业务逻辑
  • 出色的UI,可以精确控制1px;视觉统一,老设备也可以同UI运行
  • 接入平台原生功能
  • JIT 减少开发所需的时间
  • Flutter不依赖任何中间代码,最终直接构建成机器码,提高了性能。
  • 丰富的社区支持
  • 内置来自 Dart 的包管理器
  • 动态功能模块(如果你的应用包含相机功能,则可以将其设为动态模块。之后当用户想要下载并安装这个功能时就可以按需操作了。)
Flutter 的不足
  • 时间短,可能欠缺功能
  • 比 JS/TS,Flutter 可选的包较少
  • 动态更新(安卓有社区方案,但是苹果......)

    性能对比


项目1 goodluck

项目2 slots

中文网

gallery


bean
98 声望2 粉丝