React Native源码分析(二):Native和JS通信
theme: channing-cyan
系列文章
React Native源码分析(一):环境初始化以及Bundle加载
Native调用JS方法
首先在Native侧,会引入一系列接口,这些接口继承自JavaScriptModule接口,这些接口表示JS中同名模块的接口,调用Native侧接口中的方法就相当于调用JS同名模块中对应的方法,以Android启动项目访问JS侧的AppRegistry模块的runApplication为例。
先看一下在Native侧调用在ReactRootView中调用runApplication方法,接着通过CatalysInstancempl获取AppRegistry的实现类,这个实现类实际上是在JavaScriptModuleRegistry通过动态代理在JavaScriptModuleInvocationHandler中实现的,最终会回调CatalyInstanceImpl的jniCallJSFunction方法,将js侧的module名称,method名称和参数传入进去,之后就进入C++的流程了。
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信息
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方法
前面说过,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标注的对应的方法,然后进行最终的调用。
关注我的公众号:‘滑板上的老砒霜'