聊聊React-Native 、Weex、QT Mobile和Flutter跨平台技术

一、跨平台技术简介

跨平台技术主要为三类:前端

  • H5+原生(CordovaIonic微信小程序
  • JavaScript开发+原生渲染 (React NativeWeex快应用
  • 自绘UI+原生(QT for mobileFlutter)

二、Hybrid技术简介

2.1 H5+原生混合开发

这类框架主要原理就是将APP的一部分须要动态变更的内容经过H5来实现,经过原生的网页加载控件WebView (Android)或WKWebView(iOS)来加载(之后若无特殊说明,咱们用WebView来统一指代androidiOS中的网页加载控件)。这样以来,H5部分是能够随时改变而不用发版,动态化需求能知足;同时,因为h5代码只须要一次开发,就能同时在Android和iOS两个平台运行,这也能够减少开发成本,也就是说,H5部分功能越多,开发成本就越小。咱们称这种h5+原生的开发模式为混合开发 ,采用混合模式开发的APP咱们称之为混合应用Hybrid APP,若是一个应用的大多数功能都是H5实现的话,咱们称其为Web APPvue

目前混合开发框架的典型表明有:CordovaIonic微信小程序,值得一提的是微信小程序目前是在webview中渲染的,并不是原生渲染,但未来有可能会采用原生渲染。python

2.2 混合开发技术点

如以前所述,原生开发能够访问平台全部功能,而混合开发中,H5代码是运行在WebView中,而WebView实质上就是一个浏览器内核,其JavaScript依然运行在一个权限受限的沙箱中,因此对于大多数系统能力都没有访问权限,如没法访问文件系统、不能使用蓝牙等。因此,对于H5不能实现的功能,都须要原生去作。而混合框架通常都会在原生代码中预先实现一些访问系统能力的API, 而后暴露给WebView以供JavaScript调用,这样一来,WebView就成为了JavaScript与原生API之间通讯的桥梁,主要负责JavaScript与原生之间传递调用消息,而消息的传递必须遵照一个标准的协议,它规定了消息的格式与含义,咱们把依赖于WebView的用于在JavaScript与原生之间通讯并实现了某种消息传输协议的工具称之为WebView JavaScript Bridge, 简称 JsBridge,它也是混合开发框架的核心。android

总结

混合应用的优势是动态内容是H5,web技术栈,社区及资源丰富,缺点是性能很差,对于复杂用户界面或动画,WebView不堪重任。web

三、React Native、Weex及快应用

3.1 React-Native

React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 。算法

3.1.1 DOM树与控件树

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口,一种独立于平台和语言的方式访问和修改一个文档的内容和结构。换句话说,这是表示和处理一个HTML或XML文档的标准接口。简单来讲,DOM就是文档树,与用户界面控件树对应,在前端开发中一般指HTML对应的渲染树,但广义的DOM也能够指Android中的XML布局文件对应的控件树,而术语DOM操做就是指直接来操做渲染树(或控件树), 所以,能够看到其实DOM树和控件树是等价的概念,只不过前者经常使用于Web开发中,然后者经常使用于原生开发中。编程

3.1.2 React中响应式编程

  • 开发者只需关注状态转移(数据),当状态发生变化,React框架会自动根据新的状态从新构建UI。
  • React框架在接收到用户状态改变通知后,会根据当前渲染树,结合最新的状态改变,经过Diff算法,计算出树中变化的部分,而后只更新变化的部分(DOM操做),从而避免整棵树重构,提升性能。

值得注意的是,在第二步中,状态变化后React框架并不会当即去计算并渲染DOM树的变化部分,相反,React会在DOM的基础上创建一个抽象层,即虚拟DOM树,对数据和状态所作的任何改动,都会被自动高效的同步到虚拟DOM,最后再批量同步到真实DOM中,而不是每次改变都去操做一下DOM。为何不能每次改变都直接去操做DOM树?这是由于在浏览器中每一次DOM操做都有可能引发浏览器的重绘回流小程序

  • 重绘界面 : 若是DOM只是外观风格发生变化,如颜色变化,会致使浏览器重绘界面。微信小程序

  • 回流 : 若是DOM树的结构发生变化,如尺寸、布局、节点隐藏等致使,浏览器就须要回流(及从新排版布局)。浏览器

而浏览器的重绘回流都是比较昂贵的操做,若是每一次改变都直接对DOM进行操做,这会带来性能问题,而批量操做只会触发一次DOM更新。

3.1.3 React Native渲染

JavaScriptCore 是一个JavaScript解释器,它在React Native中主要有两个做用:

  • 为JavaScript提供运行环境。
  • 是JavaScript与原生应用之间通讯的桥梁,做用和JsBridge同样,事实上,在iOS中,不少JsBridge的实现都是基于 JavaScriptCore 。

而RN中将虚拟DOM映射为原生控件的过程当中分两步:

  • 布局消息传递; 将虚拟DOM布局信息传递给原生;
  • 原生根据布局信息经过对应的原生控件渲染控件树;

React Native是原生控件渲染,因此性能会比混合应用中H5好不少,同时React Native是Web开发技术栈,也只需维护一份代码,一样是跨平台框架。

3.2 Weex

Weex是阿里巴巴于2016年发布的跨平台移动端开发框架,思想及原理和React Native相似,最大的不一样是语法层面,Weex支持Vue语法和Rax语法,Rax 的 DSL(Domain Specific Language) 语法是基于 React JSX 语法而创造。与 React 不一样,在 Rax 中 JSX 是必选的,它不支持经过其它方式建立组件,因此学习 JSX 是使用 Rax 的必要基础。而React Native只支持JSX语法。

3.2.1 快应用

快应用是华为、小米、OPPO、魅族等国内9大主流手机厂商共同制定的轻量级应用标准,目标直指微信小程序。它也是采用JavaScript语言开发,原生控件渲染,与React NativeWeex相比主要有两点不一样:

  • 快应用自身不支持Vue或React语法,其采用原生JavaScript开发,其开发框架和微信小程序很像,值得一提的是小程序目前已经可使用Vue语法开发(mpvue),从原理上来说,Vue的语法也能够移植到快应用上。

  • React Native和Weex的渲染/排版引擎是集成到框架中的,每个APP都须要打包一份,安装包体积较大;而快应用渲染/排版引擎是集成到ROM中的,应用中无需打包,安装包体积小,正因如此,快应用才能在保证性能的同时作到快速分发。

总结

JavaScript开发+原生渲染的方式主要优势以下:

  • 采用Web开发技术栈,社区庞大、上手快、开发成本相对较低。

  • 原生渲染,性能相比H5提升不少。

  • 动态化较好,支持热更新。

不足:

  • 渲染时须要JavaScript和原生之间通讯,在有些场景如拖动可能会由于通讯频繁致使卡顿。

  • JavaScript为脚本语言,执行时须要JIT(Just In Time),执行效率和AOT(Ahead Of Time)代码仍有差距。

  • 因为渲染依赖原生控件,不一样平台的控件须要单独维护,而且当系统更新时,社区控件可能会滞后;除此以外,其控件系统也会受到原生UI系统限制,例如,在Android中,手势冲突消歧规则是固定的,这在使用不一样人写的控件嵌套时,手势冲突问题将会变得很是棘手。

四、 自绘制引擎

4.1 QT Mobile

自绘UI+原生。这种技术的思路是,经过在不一样平台实现一个统一接口的渲染引擎来绘制UI,而不依赖系统原生控件,因此能够作到不一样平台UI的一致性。注意,自绘引擎解决的是UI的跨平台问题,若是涉及其它系统能力调用,依然要涉及原生开发。这种平台技术的优势以下:

  • 性能高;因为自绘引擎是直接调用系统API来绘制UI,因此性能和原生控件接近。

  • 灵活、组件库易维护、UI外观保真度和一致性高;因为UI渲染不依赖原生控件,也就不须要根据不一样平台的控件单独维护一套组件库,因此代码容易维护。因为组件库是同一套代码、同一个渲染引擎,因此在不一样平台,组件显示外观能够作到高保真和高一致性;另外,因为不依赖原生控件,也就不会受原生布局系统的限制,这样布局系统会很是灵活。

不足:

  • 动态性不足;为了保证UI绘制性能,自绘UI系统通常都会采用AOT模式编译其发布包,因此应用发布后,不能像Hybrid和RN那些使用JavaScript(JIT)做为开发语言的框架那样动态下发代码。
  • 开发效率低:QT使用C++做为其开发语言,而编程须要效率是直接会影响APP开发效率的,C++做为一门静态语言,在UI开发方面灵活性不及JavaScript这样的动态语言,另外,C++须要开发者手动去管理内存分配,没有JavaScript及Java中垃圾回收(GC)的机制。

Flutter正是实现一套自绘引擎,并拥有一套本身的UI布局系统。不过,自绘制引擎的思路并非什么新概念,Flutter并非第一个尝试这么作的,在它以前有一个典型的表明,即大名鼎鼎的QT。

4.1.1 QT简介

Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。2008年,Qt Company科技被诺基亚公司收购,Qt也所以成为诺基亚旗下的编程语言工具。2012年,Qt被Digia收购。2014年4月,跨平台集成开发环境Qt Creator 3.1.0正式发布,实现了对于iOS的彻底支持,新增WinRT、Beautifier等插件,废弃了无Python接口的GDB调试支持,集成了基于Clang的C/C++代码模块,并对Android支持作出了调整,至此实现了全面支持iOS、Android、WP,它提供给应用程序开发者构建图形用户界面所需的全部功能。可是,QT虽然在PC端得到了巨大成功,备受社区追捧,然而其在移动端却表现不佳,在近几年,虽然偶尔能听到QT的声音,但一直很弱,不管QT自己技术如何、设计思想如何,但事实上终究是败了,究其缘由,笔者认为主要有四:

  • QT移动开发社区过小,学习资料不足,生态很差。

  • 官方推广不利,支持不够。

  • 移动端发力较晚,市场已被其它动态化框架占领(Hybrid和RN)。

  • 在移动开发中,C++开发和Web开发栈相比有着先天的劣势,直接结果就是QT开发效率过低。

基于此四点,尽管QT是移动端开发跨平台自绘引擎的先驱,但却成为了烈士。

4.2 Flutter

4.2.1 Flutter简介

Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者能够经过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者能够很快地为 Flutter添加 native扩展。同时 Flutter还使用 Native引擎渲染视图,这无疑能为用户提供良好的体验。

  • 2017 年 Google I/O 大会上,Google 首次推出了一款新的用于建立跨平台、高性能的移动应用框架。

  • 2018年2月,Flutter发布了第一个Beta版本,同年五月, 在2018年Google I/O 大会上,Flutter 更新到了 beta 3 版本。

  • 2018年6月,Flutter发布了首个预览版本,这意味着 Flutter 进入了正式版(1.0)发布前的最后阶段。

4.2.2 跨平台自绘引擎

Flutter与用于构建移动应用程序的其它大多数框架不一样,由于Flutter既不使用WebView,也不使用操做系统的原生控件。 相反,Flutter使用本身的高性能渲染引擎来绘制widget。这样不只能够保证在Android和iOS上UI的一致性,并且也能够避免对原生控件依赖而带来的限制及高昂的维护成本。

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

目前Flutter目前默认支持iOS、Android、Fuchsia(Google新的自研操做系统)三个移动平台。但Flutter亦可支持Web开发(Flutter for web)和PC开发,本书的示例和介绍主要是基于iOS和Android平台的,其它平台读者能够自行了解。

4.2.3 高性能

Flutter高性能主要靠两点来保证,首先,Flutter APP采用Dart语言开发。Dart在 JIT(即时编译)模式下,速度与 JavaScript基本持平。可是 Dart支持 AOT,当以 AOT模式运行时,JavaScript便远远追不上了。速度的提高对高帧率下的视图数据计算颇有帮助。其次,Flutter使用本身的渲染引擎来绘制UI,布局数据等由Dart语言直接控制,因此在布局过程当中不须要像RN那样要在JavaScript和Native之间通讯,这在一些滑动和拖动的场景下具备明显优点,由于在滑动和拖动过程每每都会引发布局发生变化,因此JavaScript须要和Native之间不停的同步布局信息,这和在浏览器中要JavaScript频繁操做DOM所带来的问题是相同的,都会带来比较可观的性能开销。

4.2.3 采用Dart语言开发

这是一个颇有意思,但也颇有争议的问题,在了解Flutter为何选择了 Dart而不是 JavaScript以前咱们先来介绍两个概念:JITAOT

目前,程序主要有两种运行方式:静态编译动态解释

  • AOT: 静态编译的程序在执行前所有被翻译为机器码,一般将这种类型称为AOT (Ahead of time)即 “提早编译”;

  • JIT: 而解释执行的则是一句一句边翻译边运行,一般将这种类型称为JIT(Just-in-time)即“即时编译”。

AOT程序的典型表明是用C/C++开发的应用,它们必须在执行前编译成机器码,而JIT的表明则很是多,如JavaScriptpython等,事实上,全部脚本语言都支持JIT模式。

但须要注意的是JITAOT指的是程序运行方式,和编程语言并不是强关联的,有些语言既能够以JIT方式运行也能够以AOT方式运行,如JavaPython,它们能够在第一次执行时编译成中间字节码、而后在以后执行时能够直接执行字节码,也许有人会说,中间字节码并不是机器码,在程序执行时仍然须要动态将字节码转为机器码,是的,这没有错,不过一般咱们区分是否为AOT的标准就是看代码在执行以前是否须要编译,只要须要编译,不管其编译产物是字节码仍是机器码,都属于AOT。在此,读者没必要纠结于概念,概念就是为了传达精神而发明的,只要读者可以理解其原理便可,得其神忘其形。

4.3 Dart和JavaScript作一个对比

如今咱们看看Flutter为何选择Dart语言?笔者根据官方解释以及本身对Flutter的理解总结了如下几条(因为其它跨平台框架都将JavaScript做为其开发语言,因此主要将DartJavaScript作一个对比):

开发效率高

Dart运行时和编译器支持Flutter的两个关键特性的组合:

基于JIT的快速开发周期:Flutter在开发阶段采用,采用JIT模式,这样就避免了每次改动都要进行编译,极大的节省了开发时间;

基于AOT的发布包: Flutter在发布时能够经过AOT生成高效的ARM代码以保证应用性能。而JavaScript则不具备这个能力。

高性能

Flutter旨在提供流畅、高保真的的UI体验。为了实现这一点,Flutter中须要可以在每一个动画帧中运行大量的代码。这意味着须要一种既能提供高性能的语言,而不会出现会丢帧的周期性暂停,而Dart支持AOT,在这一点上能够作的比JavaScript更好。

快速内存分配

Flutter框架使用函数式流,这使得它在很大程度上依赖于底层的内存分配器。所以,拥有一个可以有效地处理琐碎任务的内存分配器将显得十分重要,在缺少此功能的语言中,Flutter将没法有效地工做。固然Chrome V8的JavaScript引擎在内存分配上也已经作的很好,事实上Dart开发团队的不少成员都是来自Chrome团队的,因此在内存分配上Dart并不能做为超越JavaScript的优点,而对于Flutter来讲,它须要这样的特性,而Dart也正好知足而已。

类型安全

因为Dart是类型安全的语言,支持静态类型检测,因此能够在编译前发现一些类型的错误,并排除潜在问题,这一点对于前端开发者来讲可能会更具备吸引力。与之不一样的,JavaScript是一个弱类型语言,也所以前端社区出现了不少给JavaScript代码添加静态类型检测的扩展语言和工具,如:微软的TypeScript以及Facebook的Flow。相比之下,Dart自己就支持静态类型,这是它的一个重要优点。

Dart团队就在你身边

看似不起眼,实则举足轻重。因为有Dart团队的积极投入,Flutter团队能够得到更多、更方便的支持,正如Flutter官网所述“咱们正与Dart社区进行密切合做,以改进Dart在Flutter中的使用。例如,当咱们最初采用Dart时,该语言并无提供生成原生二进制文件的工具链(这对于实现可预测的高性能具备很大的帮助),可是如今它实现了,由于Dart团队专门为Flutter构建了它。一样,Dart VM以前已经针对吞吐量进行了优化,但团队如今正在优化VM的延迟时间,这对于Flutter的工做负载更为重要。”

技术类型 UI渲染方式 性能 开发效率 动态化 框架表明 H5+原生 WebView渲染 通常 高 支持 Cordova、Ionic JavaScript+原生渲染 原生控件渲染 好 中 支持 RN、Weex 自绘UI+原生 调用系统API渲染 好 Flutter高, QT低 默认不支持 QT、Flutter

总结

技术类型级 UI渲染方式 性能 开发效率 动态化 框架表明
H5+原生 WebView渲染 通常 支持 Cordova、Ionic
JavaScript+原生渲染 原生控件渲染 支持 RN、Weex
自绘UI+原生 调用系统API渲染 F 高 QT低 默认不支持 QT、Flutter

上表中开发语言主要指UI的开发语言。而开发效率,是指整个开发周期的效率,包括编码时间、调试时间、以及排错、兼容时间。

动态化:主要指是否支持动态下发代码是否支持热更新

值得注意的是:Flutter的Release包默认是使用Dart AOT模式编译的,因此不支持动态化;

可是Dart还有JITsnapshot运行方式,这些模式都是支持动态化的。

相关文章
相关标签/搜索