ReactNative框架Android端Native与Javascript通信原理总结
一. Native调用Javascript
整个通信过程涉及到三种程序语言:Java、C++、Javascript,Native向Javascript的单向通信流程,总结如下:
1、Java层
JavaScriptModule接口类定义通信方法,在ReactApplicationContext创建的时候存入注册表类JavaScriptModuleRegistry中,同时通过动态代理生成代理实例,并在代理拦截类JavaScriptModuleInvocationHandler中统一处理发向Javascript的所有通信请求。
CatalystInstanceImpl类内部的ReactBridge具体实现与Javascript的通信请求,它是调用Bridge Jni的出口。在ReactBridge被创建的时候会将JavaScriptModule信息表预先发给Javascript层用来生成映射表。
2、C++层
OnLoad是jni层的调用入口,注册了所有的native方法,其内部调用又都是通过CountableBridge来完成的,CountableBridge是Bridge的无实现子类,而在Bridge里面JSCExecutor才是真正的执行者。
JSCExecutor将所有来自Java层的通信请求封装成Javascript执行语句,交给WebKit内核完成向Javascript层的调用。
3、Javascript层
BatchedBridge是Javascript层的调用入口,而其又是MessageQueue的伪装者。MessageQueue预先注册了所有能够接收通信请求的组件_callableModules,同时也保存着来自Java层JavaScriptModule的两张映射表。
接收通信请求时,先通过映射表确认具体请求信息,再确认Javascript组件是否可以被调用,最后通过apply方式完成执行。
通信流程图如下:
二. Javascript调用Native
Javascript端调用Native端,同样分了三层:Javascript、Bridge、Java,概括一下主要流程。
A、Javascript层:
逻辑最为复杂的一层,NativeModules.js组件是向Native端调用的入口,其指向的又是MessageQueue的RemoteModules对象,而RemoteModules将所有的method指向了一个function函数,即__nativeCall。__nativeCall负责将所有向Native端请求的信息push进this._queue数组,在应答Native端通信请求的flushedQueue方法内将this._queue返给Bridge。
B、Bridge层:
当Bridge层接收到Javascript层的应答信息this._queue(一个JSON字符串)后,调用PlatformBridgeCallback对象的onCallNativeModules方法,onCallNativeModules里面创建了一个Runnable塞到执行Callback的线程队列中等待回调,回调中执行makeJavaCall方法,里面最终通过env->CallVoidMethod调用了Java层的方法。
C、Java层:
Bridge层中调起了Java层NativeModulesReactCallback的call方法,其里面又是NativeModuleRegistry的call调用。NativeModuleRegistry通过moduleID从保存在其内部的NativeModule映射表,匹配到需要被执行的NativeModule对象,再通过methodID匹配到NativeModule的方法。最后从ReadableNativeArray中提取出参数后通过invoke反射方式执行NativeModule的方法。
通信流程图如下:

三. Javascript调用Native,Native再回到Javascript
Javascript请求Native再回调到Javascript中,一共经历了如下流程:
一共Javascript->Bridge->Native->Bridge->Javascript五个步骤,callbackID是整个流程的关键点。
Javascript请求Native,需要先生成callbackID,并以callbackID为唯一键存储回调函数。callbackID作为上一次通信请求的应答内容传到Native端,Native接收到后通过反射NativeModule的处理方法,然后将callbackID及处理结果返给Javascript端,Javascript使用callbackID获取到存储的回调方法,然后执行。
通信流程图如下: