本文作者:邱穆
本文链接:https://juejin.cn/post/6910155874489090056
传统的原生Android、iOS开发面临着诸多难以解决的问题,例如开发周期长、迭代缓慢等,因此很多公司备受困扰。移动跨平台开发一直是移动开发者和前端开发者追求的的话题。从早期的cordova、ionic,到如今的react native、weex、H5、小程序和flutter等,跨平台开发技术百花齐放,能够生存下来保持活力的必然有其独到之处,本文就简单调研目前流行的跨平台开发技术。
如果要对目前仍在流行的跨平台的方案进行一个总结,大致可以分为以下几个流派:
React Native 和 Weex 这类方案,使用 javascript 来构建界面,在运行时翻译成原生组件展示出来,实际上所有界面都是用原生组件。支持跨平台,性能和用户体验高于 webview,接近原生应用,是当前热门的跨平台开发技术。只不过各家对编写代码支持的框架,进行翻译的时机各有不同。
ReactNative(简称RN) 是 Facebook 于2015年四月开源的跨平台移动应用开发框架,是Facebook早先开源的 Web UI 框架React在原生移动应用平台的衍生产物,目前支持 iOS 和安卓两大平台。该框架使用 JSX(JS加入了部分语法糖),以及 CSS 来开发移动应用 UI,因此熟悉 Web 开发的人只需很少的学习成本就可以转入移动应用开发。官方给出的介绍里用了一句 “Learn Once ,Write Anywhere” 还是非常贴切的,RN 并做不到一份代码很好的适配 iOS 和安卓的所有机型和系统,需要你根据具体情况去做适配。
React Native实现的原理其实就是利用JS 调用Native 端的组件,并使用Native的组件来绘制界面,从而达到媲美原生应用的效果。 和前端开发不同,React Native 所使用的标签并不是真实的控件,React Native提供的组件会Dom 转换为Native的控件进行渲染。例如 标签会被转换为Android 中对应 TextView 控件。
React Native的跨平台是实现主要由三层构成,其中 C++ 实现的动态连结库(.so),作为中间适配层桥接,实现了js端与原生端的双向通信交互。这里最核心的功能就是封装JavaScriptCore,用于执行对JavaScript的解析。同时,原生平台提供的各种原生模块(如网络请求模块、ViewGroup组件模块)和JavaScript端提供的各种模块(如JS EventEmiter模块)都会在C++层实现的.so文件中被保存起来,最终通过C++层中保存的映射实现两端的交互。其结构如如下图:
Weex是阿里巴巴开源的一套移动跨平台开发框架,能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持iOS、安卓、YunOS及Web等多端部署。目前,目前 Vue.js 和 Rax 这两个前端框架被广泛应用于 Weex 页面开发,因此Weex支持Vue语法和Rax语法,而React Native只支持JSX语法。
和 React Native一样,Weex 所有的标签也不是真实控件,Weex的标签只不过是JS 代码中所生成存的 dom,最后都是由 Native 端解析,再得到对应的Native控件渲染。如 Android 中 标签对应 WXTextView 控件。
Weex首先将编写的Weex源码,通过transformer转换成JS Bundle。然后将JS Bundle部署在服务器,当接收到终端(Android、Web端、iOS端)的JS Bundle请求时,将JS Bundle下发给终端。在终端中,由Weex的JS Framework 接收和执行JS Bundle代码,并且执行数据绑定、模板编译等操作,然后输出JSON 格式的 Virtual DOM,JS Framework发送渲染指令给Native ,提供 callNative 和 callJS 接口,方便 JS Framework 和 Native 的通信。
在移动应用客户端里,Weex SDK 会准备好一个 JavaScript 执行环境,并且在用户打开一个 Weex 页面时在这个执行环境中执行相应的 JS bundle,并将执行过程中产生的各种命令发送到 native 端进行界面渲染、数据存储、网络通信、调用设备功能及用户交互响应等功能;同时,如果用户希望使用浏览器访问这个界面,那么他可以在浏览器里打开一个相同的 web 页面,这个页面和移动应用使用相同的页面源代码,但被编译成适合Web展示的JS Bundle,通过浏览器里的 JavaScript 引擎及 Weex SDK 运行起来的。
2018 年 3 月份,由小米,OPPO,VIVO,华为等 10 家国内主流厂商成立了快应用联盟。快应用介于移动网页和原生应用之间,第三方应用以移动网页的形式进行开发,最终得到原生渲染的效果体验。快应用框架深度集成进各手机厂商的手机操作系统中,可以在操作系统层面形成用户需求与应用服务的无缝连接,很多只用在原生应用中才能使用的功能,在快应用中可以很方便的实现,享受原生应用体验,同时不用担心分发留存等问题,资源消耗也比较少。对于每台手机设备,应用可以从多个系统入口,引用用户体验产品。
快应用与 React Native 和 Weex 相比主要有两点不同:
下图是快应用的总体框架示意图。最上面是应用形态以及场景入口,中间是快应用引擎,底下是 OS(操作系统) 的基础设施及其硬件。从执行路径层面,有标准的 HTML5 方式支撑通用的 Web 场景(一般通过系统的 Webview 组件或定制的 Webview), 以及 JS(Java)+Native 的方式,支撑更轻量、更快速的体验。
小程序是混合式的移动应用,开发者在对应的平台中通过小程序的开发者工具,使用H5和JS等编写出 Native 级别的界面,通过开发者工具生成压缩包,提交到平台,然后在平台 app 中请求执行,便可实现原生 Native 的界面体验。
微信之父张小龙在他的朋友圈里写道微信小程序是不需要下载安装的应用,实现‘触手可及’,‘用完即走’的理念。这也是小程序最大的特点。
微信小程序的主要开发语言是 JavaScript ,小程序的开发同普通的网页开发相比有很大的相似性。 小程序的运行环境分成渲染层和逻辑层,这两层分别由 2 个线程管理,渲染层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS 脚本。这两个线程的通信会经由微信客户端(Native)中的 JSBridage 做中转。逻辑层发送网络请求也经由 Native 转发,小程序的框架模型下图所示。
自绘 UI 指的是通过在不同平台实现一个统一接口的渲染引擎来绘制 UI,而不依赖系统平台的原生控件,这样做可以保证不同平台 UI 的一致性。不用像 React Native 一样,随着不同平台系统版本的变化,开发者还需要处理不同平台的差异,甚至有些特性只能在单个平台上实现,这样无法保证不同平台 UI 的一致性。自绘 UI 框架的代表有 Qt 和 Flutter。
Flutter 是谷歌的移动 UI 框架,可以快速在 Android 和 iOS 上构建高质量的原生用户界面, 它的前身是谷歌试验项目 Sky。该项目可以同时运行在Android、iOS和Fuchsia等包含Dart虚拟机的平台上,并且性能无限接近原生平台。与React Native和WEEX使用JavaScript作为编程语言,以及使用平台自身引擎渲染界面不同,Flutter直接选择使用2D绘图引擎库Skia来渲染界面。
Futter 提出了一切皆 Widget 的概念,除了基本的文本、图片、卡片、输入框,布局方式和动画等也都是由 Widget 组成的。通过使用不同类型的 Widget,就可以实现复杂度的界面。
Flutter框架主要分为 Framework 和 Engine两层,我们基于Framework 开发App主要运行在 Engine 上。Engine 是 Flutter 的独立虚拟机,由它适配和提供跨平台支持,目前猜测 Flutter 应用程序在 Android 上,是直接运行 Engine 上 所以在是不需要Dalvik虚拟机。其架构图如下图所示:
与React Native和WEEX使用原生组件渲染界面不同,Flutter并不需要使用原生组件来渲染界面,而是使用自带的渲染引擎(Engine层)来绘制页面组件(Flutter显示单元),并且Dart代码会通过AOT被编译为对应平台的原生代码,实现与平台的直接通信,不需要通过JavaScript引擎进行桥接,也不需要使用原生平台的Dalvik虚拟机。Engine层的渲染架构图如下:
Flutter唯一要求系统提供的是canvas,用以实现UI的绘制。不过,Flutter 上 Android 自带了 Skia,Skia是一个 2D的绘图引擎库,跨平台,所以可以被嵌入到 Flutter的 iOS SDK中,也使得 Flutter Android SDK要比 iOS SDK小很多。
Qt产生的时间很早,Qt 第一版于 1991 年由 Trolltech 发布。后来在 2008 年,Nokia 斥资 1.5 亿美元收购 TrollTech,将 Qt 应用于 Symbian 程序开发。2012 年 8 月 9 日,Nokia 将 Qt 以 400 万欧元的价格出售给 Digia。2016年Qt Group Plc从Digia分拆出来,2014年Qt开始支持移动端的Android、iOS、Wp平台。虽然Qt在PC领域发展良好,但在移动端表现不佳,很少有人提及或者用Qt去开发移动端。
Web、React-Native、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。
说来可笑,跨平台技术本来是为了兼容多端开发的技术,现在反而需要开发一套技术去兼容不同的跨平台技术。
跨平台兼容较多的为Taro,uni-app,chameleon等3款产品;若只需兼容微信小程序的话则市场上使用较多的是mpvue及WePy;
通过一张表格来简单总结下这种技术:
总体来说,Flutter是目前最好的跨平台解决方案之一,它只用一套代码便可生成Android和iOS两种平台上的应用,很大程度上减少了App的开发和维护成本。同时,Dart语言强大的性能表现和丰富的特性,也使得跨平台开发变得更加便利。而不足的是,Flutter还处于初期测试阶段,许多功能还不是特别完善,而全新的Dart语言也增加了开发者的学习成本。Flutter要完全替代Android和iOS原生开发,还有比较长的路要走。
本文作者:邱穆
本文链接:https://juejin.cn/post/6910155874489090056