Facebook于2015年9月15日发布了ReactNativeforAndroid,将JavaScript开发技术扩展到Android平台。ReactNative允许开发者使用JavaScript和React编写应用程序,并使用相同的核心代码创建基于Web、iOS和Android平台的原生应用程序。本文将简要分析AndroidReact的架构及相关基础知识。环境搭建和调试相关知识参考官网文档(https://facebook.github.io/react-native/),本文不再赘述。1.React架构分析1)层次架构:Java层:java层是逻辑入口,启动C++层的javascript解析器,通过c++执行js传过来的渲染指令,构建NativeUI等。java层依赖在许多优秀的开源库上。Fresco用于图像处理,okhttp用于网络通信。当然还有很多工具,比如Json分析工具jackson,知名的Animation开源库NineOldAndroids,还有小而全的底层工具。Bolts等在java层被打包为Modules。java层的核心jar包是react-native.jar,里面封装了很多上层的接口,比如Module、Registry、bridge等,下面将根据启用流程全面分析java层的架构应用程序。C++层:C++层主要封装JavaScriptCore,执行js的解析。基于JavaScriptCore,web开发者可以充分使用ES6的新特性,如类、箭头运算符等,而ReactNative运行在JavaScriptCore中,完全没有浏览器兼容性。Bridge桥接java<>js通信的核心接口。JSLoader主要是从assets目录或者本地文件加载文件到javascriptCore,然后通过JSCExecutor解析js文件。js层:主要处理事件分发和UILayout,主要有以下几个组件:渲染引擎可用于生成不同平台下的用户界面。组件的使用在React中极其重要,因为组件的存在使得计算DOMdiff的效率更高。Lifecycle&Data:React组件通过内部状态变量控制生命周期和事件回调。例如getInitialState方法用于定义组件的初始状态,后续组件可以通过this.state属性读取状态。当事件触发(或主动调用setState方法更新数据)导致状态发生变化时,this.setState方法会修改状态值。每次修改后,都会自动调用this.render方法重新渲染组件。Layout:React使用css-layout,css-layout使用javascript实现flexbox,不依赖DOM,可以编译成Object-C或者Java,最终达到跨平台展示的目的,但是不支持css3for暂时只能支持简单的布局和一般的动画。2)Js与Java通信机制:同一个模块配置表分别存放在Java层和Js层的bridge中。Java与Js通信时,将调用的模块方法通过bridge中的配置表转换为{moduleID,methodID,args}传给处理层,处理层通过模块配置表找到对应的方法执行桥的。如果有回调,则返回调用层。在了解了ReactAndroidAPP的启动之后,第三部分会详细讲一下这个机制。2.从应用启动到页面加载完成的分析上图是AndroidReact的加载过程分析。下面先简单介绍一下上层的核心类和原理,再梳理一下核心的使能步骤。核心类:1.ReactInstanceManager:主要用于创建和管理Catalyst实例的上层接口,控制开发调试,与ReactRootView所在的Activity保持生命周期一致。2.ReactRootView:启动入口的核心类,负责监听分发事件,重新渲染元素。App启动后,它将作为App的根视图。3.CatalystInstance:***异步JSCAPI封装类,提供Java和Js互通的环境,通过ReactBridge将Svr的JsBundle传递给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向NodeSvr请求JsBundle,传递给JSCJavaScriptExectutor,最后传递给javascriptCore,然后通过ReactBridge通知ReactRootView完成渲染。3、Js与Java的通信机制Java与Js的调用是建立在双方存在同一个模块配置表的基础上的。最终调用转化为{moduleID,methodID,callbackID,args},处理端在模块配置表中找到注册的模块和方法并调用。Java->Js:Java通过registry调用CatalystInstance实例,通过ReactBridge的jni调用Onload.cpp中的callFunction,通过javascriptCore调用BatchedBridge.js,根据参数{moduleID,methodID}需要对应的Js模块执行.详细过程如下图所示。Js->Java:JS不主动传递数据调用Java。当需要调用Java模块方法时,会将参数{moduleID,methodID}等数据存放在MessageQueue中,等待Java事件触发,然后将MessageQueue中的{moduleID,methodID}返回给Java,然后根据模块注册表找到对应的模块。模块处理。详细过程如下图所示。4.总结React将UI分解成组件,抛弃模板,统一视图逻辑标签,使得构建的视图更易于扩展和维护。VirtualDom是其性能提升的亮点。React中的Dom不保证它会立即影响真实的。Dom,React会等到事件循环结束,并使用diff算法将当前新的Dom树与之前的Dom树进行比较,计算出更新真实DOM的最小步数。AndroidReact的引入使得使用相同的核心代码在Web、iOS和Android平台上创建原生应用程序成为可能。但目前AndroidReact的HelloWorld基础库近7m,落地项目还需精简。我们目前正在精简。当然也有Android版本的测试,只支持Android4.1(API16)(iOS7.0)以上的版本。当然,如果系统不支持,H5可以作为备用方案。我们会持续关注AndroidReact的动态,持续为大家推送更多关于AndroidReact的文章。(底部有所有AndroidReact库的说明)
