版权声明:本文由王少鸣原创文章,转载请注明出处: 
文章原文链接:https://www.qcloud.com/community/article/171

来源:腾云阁 https://www.qcloud.com/community

Facebook 在2015.9.15发布了 React Native for Android,把JavaScript 开发技术扩展到了Android平台。React Native 让开发者使用 JavaScript 和 React 编写应用,利用相同的核心代码就可以创建 基于Web,iOS 和 Android 平台的原生应用。本文将浅析Android React的架构及相关基础知识。
环境搭建及调试相关知识参考官网文档即可,本文不再赘述。

一.React架构分析

1.层次架构:


Java层:java层为逻辑入口,启动C++层的javascript解析器,执行js通过c++传递来的渲染指令,从而构建NativeUI等。java层依赖于众多优秀开源库,在图片处理使用的是Fresco,网络通信使用的是okhttp,当然还有众多工具类,如Json解析工具jackson,Animation知名开源库NineOldAndroids,小而全的底层工具类bolts等,在java层均封装为Module。java层核心jar包是react-native.jar,封装了众多上层的interface,如Module,Registry,bridge等,下面会以App的启用过程,完整分析java层的架构。

C++层:c++层最主要是封装了JavaScriptCore,执行对js的解析。基于JavaScriptCore,Web开发者可以尽情使用ES6的新特性,如class、箭头操作符等,而且 React Native运行在JavaScriptCore中的,完全不存在浏览器兼容的情况。Bridge桥接了java <> js 通信的核心接口。JSLoader主要是将来自assets目录的或本地file加载到javascriptCore,再通过JSCExectutor解析js文件。

Js层:主要处理事件分发及UI Layout,主要有以下几个部件:

  • Component:Js层通js/jsx编写的Virtual Dom来构建Component或Module,Virtual DOM是DOM在内存中的一种轻量级表达方式,可以通过不同的渲染引擎生成不同平台下的UI。component的使用在 React 里极为重要, 因为component的存在让计算 DOM diff 更高效。
  • Lifecycle&Data:React 组件通过内部的 state 变量控制生命周期及事件回调。如getInitialState方法用于定义组件初始状态,后续组件可通过 this.state 属性读取该状态。当事件触发(或者主动调用setState方法更新数据)导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,重新渲染组件。
  • Layout:React使用css-layout,css-layout使用javascript实现了flexbox ,不依赖于DOM,能编译成Object-C或者Java,最终达到跨平台的展示目的,但暂时不支持css3,暂时只能支持简单的布局和普通的动画。

2.Js与Java通信机制:

在Java层与Js层的bridge分别存有相同一份模块配置表,Java与Js互相通信时,通过bridge里的配置表将所调用模块方法转为{moduleID,methodID,args}的形式传递给处理层,处理层通过bridge的模块配置表找到对应的方法执行,如果有callback,则回传给调用层。在了解ReactAndroid APP启动后,第三部分会详细讲这套机制。

二.从应用启动到页面加载完成分析


上图为 Android React 加载过程的解析,下面先概要描述上层核心类及原理,再梳理核心的启用步骤。
Core Class:
1.ReactInstanceManager:主要是用来创建及管理Catalyst的实例的上层接口,控制开发调试,生命周期与ReactRootView所在activity保持一致。

2.ReactRootView:为启动入口核心类,负责监听及分发事件并重新渲染元素,App启动后,其将作为App的root view。

3.CatalystInstance:顶级异步JSCAPI封装类,提供Java与Js互通的环境,通过ReactBridge将Svr的Js Bundle传送到Js引擎。

4.NativeModuleRegistry:Java层模块注册表,即暴露给Js的API集合。

5.JavascriptModuleRegistry:Js层模块注册表,负责将所有JavaScriptModule注册到CatalystInstance,通过Java动态代理调用到Js。

6.CoreModulePackage:定义核心框架模块,创建NativeModules&JsModules。

启动过程的解析:

1.在ReactInstanceManager时会配置应用所需的java模块与js模块之后,通过ReactRootView的startReactApplication启动APP。

2.在创建ReactInstanceManager同时会创建用于加载JsBundle的JSBundlerLoader,并传递给CatalystInstance。

3.CatalystInstance会创建Java模块注册表及Javascript模块注册表,并遍历实例化模块。

4.CatalystInstance通过JSBundlerLoader向Node Svr请求Js Bundle,并传递给JSCJavaScriptExectutor,最后传递给javascriptCore,再通过ReactBridge通知ReactRootView完成渲染。

三.Js与Java通信机制

Java与Js之间的调用,是以两边存在两边存在同一份模块配置表,最终均是将调用转化为{moduleID, methodID,callbackID,args},处理端在模块配置表里查找注册的模块与方法并调用。
Java -> Js :Java通过注册表调用到CatalystInstance实例,透过ReactBridge的jni,调用到Onload.cpp中的callFunction,最后通过javascriptCore,调用BatchedBridge.js,根据参数{moduleID,methodID}require相应Js模块执行。详细流程如下图。

Js -> Java:JS不主动传递数据调用Java。在需要调用调Java模块方法时,会把参数{moduleID,methodID}等数据存在MessageQueue中,等待Java的事件触发,再把MessageQueue中的{moduleID,methodID}返回给Java,再根据模块注册表找到相应模块处理。详细流程如下图。

四.总结

React将UI分解成组件,废弃了模板,统一视图逻辑标签,使构建的视图更容易扩展和维护,Vitual Dom更是其提高性能的亮点,React 中的Dom并不保证马上影响真实的Dom,React会等到事件循环结束,利用diff算法,通过当前新Dom树与之前的Dom树作比较,计算出最小的步骤更新真实的DOM。
Android React的推出更使得利用相同的核心代码就可以创建 Web,iOS 和 Android 平台的原生应用,但目前Android React的HelloWorld基础库将近7m,落地项目仍需要精简,目前我们正在精简中。当然,对于Andriod版本也有考验,仅支持 Android 4.1 (API 16) 以上的版本(iOS 7.0),当然,在系统不支持情况下,H5可以作为后备方案。
我们后续会持续关注Android React的动态,向大家继续推送更多关于Android React的文章。(底部有关于Android React所有类库的描述)

React Native For Android 架构初探的更多相关文章

  1. React native 之android的图标和启动图片

    哎哎呀呀,上篇说到了react native的IOS的图标和启动图片的设置,其实最主要的是尺寸!相应的尺寸设定好了以后就不会报错了! ok~这篇说的是React native的android的图标和启 ...

  2. 【React Native开发】React Native For Android环境配置以及第一个实例(1)

    年9月15日也公布了ReactNative for Android,尽管Android版本号的项目公布比較迟,可是也没有阻挡了广大开发人员的热情.能够这样讲在2015年移动平台市场上有两个方向技术研究 ...

  3. React Native for Android 学习

    前言 Facebook 在2015.9.15发布了 React Native for Android,把 JavaScript 开发技术扩展到了移动Android平台.基于React的React Na ...

  4. React Native for android 项目驱动教程

    第一节 搭建开发环境 第二节 显示页面标题 第三节 实现页面布局 # React native是什么? React Native,是颠覆性的移动开发技术.它使用js开发,又是原生应用,不同于Hybri ...

  5. React Native之新架构中的Turbo Module实现原理分析

    有段时间没更新博客了,之前计划由浅到深.从应用到原理,更新一些RN的相关博客.之前陆续的更新了6篇RN应用的相关博客(传送门),后边因时间问题没有继续更新.主要是平时空余时间都用来帮着带娃了,不过还是 ...

  6. React Native for Android应用名及图标修改

    应用开发完了,总不能顶着MyProject和小机器人图标就发布了吧?在发布之前,有多处需要修改的地方.今天我们来全面的看一下 应用ID 俗称PackageName,或APP ID.注意,在gradle ...

  7. react native 之 Android物理返回键

    基本用法 根据文档,安卓back键的处理主要就是一个事件监听: BackAndroid.addEventListener('hardwareBackPress', this.onBackPressed ...

  8. React Native for Android 热部署图片自己定义方案

    情景 热部署时,我们期望升级包中包括js代码与图片资源. bundle的热部署网上已经有两种方案了,一种是用反射,一种是利用RN自带函数.将bundle初始化时直接放到指定文件夹下,之后通过替换bun ...

  9. 混合开发的大趋势之一React Native与Android联调

    转载请注明出处:王亟亟的大牛之路 先安利,有空我都会更,看到的好东西都会放进来:https://github.com/ddwhan0123/Useful-Open-Source-Android 公司某 ...

随机推荐

  1. UPC 2170 D Equal Is Not Really Equal (欧拉路径)

    题目链接:http://acm.upc.edu.cn/problem.php?id=2170 题意:给出一个字符串,比如ABACA,在这个串里,AB.BA.AC.CA各出现一次.若存在另外一个串,里面 ...

  2. jquery之event与originalEvent的关系、event事件对象用法浅析

    在jquery中,最终传入事件处理程序的 event 其实已经被 jQuery 做过标准化处理, 其原有的事件对象则被保存于 event 对象的 originalEvent 属性之中, 每个 even ...

  3. Hibernate 查询语句

    Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据 ...

  4. 04_IOC容器装配Bean(xml方式)

    IOC容器装配Bean(xml方式) 1.Spring 提供配置Bean三种实例化方式 1)使用类构造器实例化(默认无参数) <bean id="bean1" class=& ...

  5. Open SQL详解

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. 快速查看SQL Server 中各表的数据量以及占用空间大小

    快速查看SQL Server 中各表的数据量以及占用空间大小. CREATE TABLE #T (NAME nvarchar(100),ROWS char(20),reserved varchar(1 ...

  7. ubuntu下卸载vmware

    直接crl+alt+t打开一个terminal,然后输入sudo vmware-installer --uninstall-product vmware-workstation即可卸载!操作如下图: ...

  8. plot bar chart using python

    Example import matplotlib.pyplot as plt import plotly.plotly as py # Learn about API authentication ...

  9. 一个异常与Android Studio系列教程参考

    由于编译过程中遇到了错误:

  10. DOM 表单应用

    1.大小写转换 <script> var a='aaa'; var b='AaA'; var c='BbB'; //alert(c.toLowerCase()); //把含有大写的字母转换 ...