前言:hybrid混合开发方案不在本篇讨论范围。本篇分析的是以原生代码运行在设备上跨平台方案。
写一套代码可以分别编译出apk和ipa在Android和iOS上运行。learn once ,write once run android&ios
开发一款Android APP需要学哪些知识?需要学习JAVA,需要学习Android框架,需要学习Android上的四大组件等等。
开发一款IOS APP需要学习哪些知识?需要学习OC或者swift,需要学习iOS的各种API
当一款APP需要在两个平台开发的时候,财大气粗的就是招两拨人,一拨人Android开发,一拨iOS开发,人力成本很高。节约成本呢就是让Android 开发去学习IOS开发,或者让IOS开发去学习Android开发,这样是节省了人力但是学习的时间成本呢?
有了跨平台方案,我们只需要学习一套框架,一种语言,写一套代码(理想情况)。
设计理念:
Facebook对ReactNative的定义是Learn once, write anywhere 意思就是学习一种语言和框架可以做任何项目(Android、IOS、web),RN用的是React设计模式,UI的渲染是通过原生代码实现,JS代码编写的控件通过
ReactNative框架内的中间件转化为原生代码运行。
如下图所示,react native 的跨平台是实现主要由三层构成,其中 C++ 实现的动态连结库(.so),作为中间适配层桥接,实现了js端与原生端的双向通信交互。这里最主要是封装了 JavaScriptCore
执行js的解析,而 react native 运行在JavaScriptCore中,所以不存在浏览器兼容的问题。
其中在IOS上直接使用内置的javascriptcore
, 在Android 则使用webkit.org官方开源的jsc.so
。
实现原理:
和前端开发不同,react native 所有的标签都不是真实控件,JS代码中所写控件的作用,类似 Map 中的 key 值。JS端通过这个 key 组合的 Dom ,最后Native端会解析这个 Dom ,得到对应的Native控件渲染,如 Android 中
标签对应 ViewGroup
控件。
在 react native 中,JS端是运行在独立的线程中(称为JS Thread )。JS Thread 作为单线程逻辑,不可能处理耗时的操作。那么如 fetch
、图片加载
、 数据持久化
等操作,在 Android 中实际对应的是 okhttp
、Fresco
、SharedPreferences
等。而跨线程通信,也意味着 Js Thread 和原生之间交互与通讯是异步的。
可以看出,跨平台的关键在于C++层,开发人员大部分时候,只专注于JS 端的代码实现。 在原生端提供的各种 Native Module 模块(如网络请求,ViewGroup控件),和 JS 端提供的各种 JS Module(如JS EventEmiter模块),都会在C++实现的so中保存起来,双方的通讯通过C++中的保存的映射,最终实现两端的交互。通信的数据和指令,在中间层会被转为String字符串传输,双向的调用流程如下图。
Flutter 是谷歌2018年发布的跨平台移动UI框架。相较于本人已经在项目中使用过 react native 和 Weex,Flutter目前仅仅是简单运行过Demo,毕竟还是beta 阶段,这里更多的聊一下它的实现机制和效果。
与 react native 和 weex 的通过 Javascript 开发不同,Flutter 的编程语言是Drat,(谷歌亲儿子,据说是因为 Drat 项目组就在 Flutter 隔壁而被选上(◐‿◑))所以执行时并不需要 Javascript 引擎,但实际效果最终也通过原生渲染。
如上图,Flutter 主要分为 Framework
和 Engine
,我们基于Framework 开发App,运行在 Engine 上。Engine 是 Flutter 的独立虚拟机,由它适配和提供跨平台支持,目前猜测 Flutter 应用程序在 Android 上,是直接运行 Engine 上 所以在是不需要Dalvik虚拟机。(这是比kotlin更彻底,抛弃JVM的纠缠?)
如下图,得益于 Engine 层,Flutter 甚至不使用移动平台的原生控件, 而是使用自己 Engine 来绘制 Widget (Flutter的显示单元),而 Dart 代码都是通过 AOT 编译为平台的原生代码,所以 Flutter 可以 直接与平台通信,不需要JS引擎的桥接。同时 Flutter 唯一要求系统提供的是 canvas,以实现UI的绘制。咦?这么想来,支持web端也没问题吧!
在Flutter中,大多数东西都是widget,而widget是不可变的,仅支持一帧,并且在每一帧上不会直接更新,要更新而必须使用Widget的状态。无状态和有状态 widget 的核心特性是相同的,每一帧它们都会重新构建,有一个State对象,它可以跨帧存储状态数据并恢复它。
RN和Flutter都是非常强大的跨平台框架,性能都不错,理论上Flutter性能更好。
这两种都不适合在现有成熟项目内添加,适合开发新项目。
参考文档
:https://www.jianshu.com/p/7e0bd4708ba7