React Native源码分析(二):Native和JS通信

873 阅读3分钟

系列文章

React Native源码分析(一):环境初始化以及Bundle加载

Native调用JS方法

首先在Native侧,会引入一系列接口,这些接口继承自JavaScriptModule接口,这些接口表示JS中同名模块的接口,调用Native侧接口中的方法就相当于调用JS同名模块中对应的方法,以Android启动项目访问JS侧的AppRegistry模块的runApplication为例。

RNNative调用jsjava.jpg

先看一下在Native侧调用在ReactRootView中调用runApplication方法,接着通过CatalysInstancempl获取AppRegistry的实现类,这个实现类实际上是在JavaScriptModuleRegistry通过动态代理在JavaScriptModuleInvocationHandler中实现的,最终会回调CatalyInstanceImpl的jniCallJSFunction方法,将js侧的module名称,method名称和参数传入进去,之后就进入C++的流程了。

native到jsc++.jpg CatalyInstanceImpl.cpp首先调用了Instance的callJSFunction,接着Instance会调用NatieToJsBridge的callFunction,然后调用MessageQueueThread的runOnQueue方法,MessageThread是在Java侧初始化CatalyInstanceImpl的时候创建ReactQueueConfigurationImpl时创建的MessageQueueThread,在这里会有创建三个MessageQueueThread,一个js线程,用来native调用js方法,一个native线程,用来js调用native方法,一个UI线程,每个MessageQueueThread都有以个Looper和Handler。MessageQueueThread的runOnQueue方法会将一个runnable方法注入java侧Looper,等到调用时会调用JSIExecutor的callFunction方法,这个JSIExecutor实际上可以粗略理解为js引擎,通过模板注入不同的js侧运行时runtime实现和js引擎的解耦。JSIExecutor调用在js侧MessageQueue模块实现的callFunctionReturnedFlushedQueue方法,传入js模块名、方法名和参数,完成js侧的方法调用后,然后会调用JSIExecutor的callNativeModules方法,将js调用native队列中的所有方法进行一遍调用,同时回调Native侧的onBathCompleted方法,至此Native到js侧方法的调用流程就结束了。

JS调用Native方法

创建NativeModules信息

js到native通信创建native模块.jpg

java侧ReactInstanceManager在创建ReactContext的时候会处理所有注入的ReactPackage,解析其中所有的createNativeModules方法返回的NativeModuleHolder map,并且通过NativeModuleRegistry持有所有该list对象,通过CatalyInstanceImpl创建的时候在调用initlizedBridge方法时进入c++侧,同时传入的所有JavaModuleWrapper的list和C++的本地方法的ModuleHolder list。根据传入的JavaModuleWrapper的list和ModuleHoder的list,创建C++本地的ModuleRegistry.cpp,然后通过initializeRuntime方法调用NativeToJsBidge的方法,NativeToJsBridge持有JSIExecutor,调用它的initializeRuntime方法,然后设置NativeModuleProxy为js侧对应的nativeModuleProxy对象,最终会赋值给js侧的NativeModules对象,NativeModules其实就是一个map,而NativeModuleProxy会持有JSINativeModules,其中JSINativeModules会持有之前创建的本地C++ ModuleRegistry对象,而ModuleRegistry包含所有的NativeModules信息,至此NativeModules信息构建完成。

调用Native方法

js到native通信2.jpg 前面说过,NativeModules.js对应的实现其实就是C++侧的NativeModuleProxy.cpp,所以NativeModules.ModuleName其实就是访问NativeModuleProxy的get方法,NativeModuleProxy持有了JSINativeModules,然后调用NativeModuleProxy的getModule方法,在这里会有一个混窜逻辑,如果之前已经创建过对应的NativeModule,那么直接返回,否则就会调用ModuleRegistry的getConfig方法用来获取对应NativeModule的配置信息,这个配置信息包含Module名称、native暴露给js侧的常量,方法名数组以及异步方法id数组和同步方法id数组。这些信息的获取其实是通过Native侧的JavaModuleWrapper.java实现的,通过调用它的一些列对应方法,获取相应的NativeModule的配置信息,而这些配置信息最终会写入js侧的NativeModules里,前面说过,NativeModules就是一个map。调用NativeModules的异步方法时最终会调用到MessageQueue.enqueueNativeCall方法,最终会通过NativeToJsBridge.cpp调用Native侧的JavaModuleWrapper的invoke方法,这里就会根据methodId找到在NativeModule中用@ReactMethod标注的对应的方法,然后进行最终的调用。

关注我的公众号:‘滑板上的老砒霜'