首先来看一下一张完整Native与JavaScript交互原理图:
在 React Native App中,在应用启动时根据 ReactPackage 会自动生成 JavaScriptModuleRegistry和NativeModuleRegistry两份模块配置表,包含系统CoreModulesPackage, 基础模块MainReactPackage以及自定义模块。Java端与JavaScript端持有相同的模块配置表,标识为可识别为Native模块或JavaScript模块都是通过实现相应接口,并将实例添加ReactPackage的CreactModules方法即可。
一. Native启动React Application
JavaScript模块extends JavascriptModule, JavaScript模块通过java动态代理实现调用Js模块。下例 AppRegistry.java 为在加载完 Jsbundle 后,Native 去启动 React Application 的总入口,appkey 为应用的 ID。映射每个 JavascriptModule 的信息保存在 JavaScriptModuleRegistration 中,统一由 JavaScriptModuleRegistry统一管理。
1. setupReactContext
ReactInstanceManagerImpl.java 中 ReactContextInitAsyncTask.setupReactContext() 方法中如下调用:
((AppRegistry)catalystInstance.getJSModule(AppRegistry.class)).runApplication(appkey, appParams);
2. Java动态代理
JS模块通过java动态代理实现调用JS方法,java动态代理通过实现InvocationHandler接口,然后通过Proxy.newProxyInstance()实现. 方法有三个参数:
-
类加载器(Class Loader)
-
需要实现的接口数组
-
所有动态代理类的方法调用,都会交由InvocationHandler接口实现类里的invoke()方法去处理。这是动态代理的关键所在。
(JavaScriptModule)Proxy.newProxyInstance(moduleInterface.getClassLoader(), new Class[]{moduleInterface},
new JavaScriptModuleRegistry.JavaScriptModuleInvocationHandler(executorToken, instance, registration));
3.JavaScript模块:继承JavascriptModule实现自定义JavaScript模块。
public interface AppRegistry extends JavaScriptModule {
void runApplication(String appKey, WritableMap appParameters);
void unmountApplicationComponentAtRootTag(int rootNodeTag);
}
4.实现 InvocationHandler接口,实现invoke方法,invoke 调用 callFunction实现js的调用。
private static class JavaScriptModuleInvocationHandler implements InvocationHandler {
@Nullable
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
ExecutorToken executorToken = (ExecutorToken)this.mExecutorToken.get();
if(executorToken == null) {
FLog.w("React", "Dropping JS call, ExecutorToken went away...");
return null;
} else {
String tracingName = this.mModuleRegistration.getTracingName(method);
WritableNativeArray jsArgs = args != null?Arguments.fromJavaArgs(args):new WritableNativeArray();
this.mCatalystInstance.callFunction(executorToken, this.mModuleRegistration.getName(), method.getName(), jsArgs, tracingName);
return null;
}
}
}
5.callFunction JNI调用流程详细流程:
1.OnLoad.cpp:
static void callFunction(JNIEnv* env, jobject obj, JExecutorToken::jhybridobject jExecutorToken, jstring module, jstring method,
2.Bridge.cpp
void Bridge::callFunction(ExecutorToken executorToken,const std::string& moduleId,const std::string& methodId,const folly::dynamic& arguments,const std::string& tracingName)
3.JSCExecutor.cpp
1. void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments)
// 确保fbBatchedBridge 有定义
2. bool JSCExecutor::ensureBatchedBridgeObject()
// 执行fbBatchedBridge中js方法
3. void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) {
4. 执行js fbBatchedBridge.callFunctionReturnFlushedQueue 返回queue队列
5. 执行Bridge.cpp : void Bridge::callNativeModules(JSExecutor& executor, const std::string& callJSON, bool isEndOfBatch)
6. 执行 m_callback->onCallNativeModules(getTokenForExecutor(executor), callJSON, isEndOfBatch);
m_callback 为OnLoad.cpp 中的 class PlatformBridgeCallback : public BridgeCallback
相当于执行 PlatformBridgeCallback.onCallNativeModules
7. 最后调用 makeJavaCall方法调用java方法
8. OnLoad.cpp 中 makeJavaCall 定义, c++通过CallVoidMethod调用java非静态方法:
gCallbackMethod 定义:
jclass callbackClass = env->FindClass("com/facebook/react/bridge/ReactCallback");
bridge::gCallbackMethod = env->GetMethodID(callbackClass, "call", "(Lcom/facebook/react/bridge/ExecutorToken;IILcom/facebook/react/bridge/ReadableNativeArray;)V");
static void makeJavaCall(JNIEnv* env, ExecutorToken executorToken, jobject callback, const MethodCall& call) {
auto newArray = ReadableNativeArray::newObjectCxxArgs(std::move(call.arguments));
env->CallVoidMethod(
callback,
gCallbackMethod,
static_cast<JExecutorTokenHolder*>(executorToken.getPlatformExecutorToken().get())->getJobj(),
call.moduleId,
call.methodId,
newArray.get());
}
二. JavaScript启动流程
JavaScript初始化
在JSBundle.js文件底部有两个require调用:
require(191); // require(‘InitializeJavaScriptAppEngine’)
InitializeJavaScriptAppEngine 初始化,主要包括Map,Set,XHR, Timer, Log,Fetch,WebSocket PolyfillRCTDeviceEventEmitter,RCTNativeAppEventEmitter,PerformanceLogger初始化
require(0); // require(‘SmartRectNativeApp/debug.android.js’)
JS启动入口,其中会引用require('react') 和 require('react-native')
ReactNative.AppRegistry.registerComponent('SmartDebugReactApp', function () {
return SmartRectNativeApp;
});
下面具体梳理一下require(0)后启动流程
1. BatchedBridge, MessageQueue, NativeModules初始化
通过MessageQueue定义RemoteModules对象
function MessageQueue(configProvider) {
lazyProperty(this, 'RemoteModules', function () {
var _configProvider =configProvider();
var remoteModuleConfig = _configProvider.remoteModuleConfig;
var modulesConfig = this._genModulesConfig(remoteModuleConfig);
// 初始化所有JS调用Native模块
var modules = this._genModules(modulesConfig);
return modules;
});
}
2. Bridge全局配置表
__fbBatchedBridgeConfig 由Native层注入的全局对象,数据格式如下,包含remoteModuleConfig节点。节点信息包括:moduleName, methodId, methodName, args。
var BatchedBridge = new MessageQueue(function () {return global.__fbBatchedBridgeConfig;});
{
"remoteModuleConfig": {
"FrescoModule": {
"moduleID": 0,
"supportsWebWorkers": false,
"methods": {}
},
"RNIntentModule": {
"moduleID": 1,
"supportsWebWorkers": false,
"methods": {
"openThirdReactActivity": {
"methodID": 0,
"type": "remote"
},
"openSecondReactActivity": {
"methodID": 1,
"type": "remote"
},
"getDataFromIntent": {
"methodID": 2,
"type": "remote"
},
"finishActivity": {
"methodID": 3,
"type": "remote"
},
"backActivity": {
"methodID": 4,
"type": "remote"
},
"openSecondActivity": {
"methodID": 5,
"type": "remote"
}
}
}
}
3. NativeModules实现
define(60 /* NativeModules */, function (global, require, module, exports) {
'use strict';
var BatchedBridge = require(61 /* BatchedBridge */);
var RemoteModules = BatchedBridge.RemoteModules;
function normalizePrefix(moduleName) {
return moduleName.replace(/^(RCT|RK)/, '');
}
Object.keys(RemoteModules).forEach(function (moduleName) {
var strippedName = normalizePrefix(moduleName);
if (RemoteModules['RCT' + strippedName] && RemoteModules['RK' + strippedName]) {
throw new Error(
'Module cannot be registered as both RCT and RK: ' + moduleName);
}
if (strippedName !== moduleName) {
RemoteModules[strippedName] = RemoteModules[moduleName];
delete RemoteModules[moduleName];
}
});
var NativeModules = {};
Object.keys(RemoteModules).forEach(function (moduleName) {
Object.defineProperty(NativeModules, moduleName, {
configurable: true,
enumerable: true,
get: function get() {
var module = RemoteModules[moduleName];
if (module && typeof module.moduleID === 'number' && global.nativeRequireModuleConfig) {
var json = global.nativeRequireModuleConfig(moduleName);
var config = json && JSON.parse(json);
module = config && BatchedBridge.processModuleConfig(config, module.moduleID);
RemoteModules[moduleName] = module;
}
Object.defineProperty(NativeModules, moduleName, {
configurable: true,
enumerable: true,
value: module
});
return module;
}
});
});
module.exports = NativeModules;
}, "NativeModules");
4. _genModules 调用 _genModule
function _genModules(remoteModules) {
var _this5 = this;
var modules = {};
remoteModules.forEach(function (config, moduleID) {
var info = _this5._genModule(config, moduleID);
if (info) {
modules[info.name] = info.module;
}
});
return modules;
}
5. _genModule 调用 _genMethod
function _genModule(config, moduleID) {
module[methodName] = _this6._genMethod(moduleID, methodID, methodType);
return { name: moduleName, module: module };
}
6. _genMethod 调用 __nativeCall 返回 Promise或function
function _genMethod 调用 (module, method, type) {
var fn = null;
var self = this;
if (type === MethodTypes.remoteAsync) {
fn = function fn() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return new Promise(function (resolve, reject) {
self.__nativeCall(
module,
method,
args,
function (data) {
resolve(data);
},
function (errorData) {
var error = createErrorFromErrorData(errorData);
reject(error);
});
});
};
} else if (type === MethodTypes.syncHook) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return global.nativeCallSyncHook(module, method, args);
};
} else {
fn = function fn() {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
var lastArg = args.length > 0 ? args[args.length - 1] : null;
var secondLastArg = args.length > 1 ? args[args.length - 2] : null;
var hasSuccCB = typeof lastArg === 'function';
var hasErrorCB = typeof secondLastArg === 'function';
hasErrorCB && invariant(
hasSuccCB,
'Cannot have a non-function arg after a function arg.');
var numCBs = hasSuccCB + hasErrorCB;
var onSucc = hasSuccCB ? lastArg : null;
var onFail = hasErrorCB ? secondLastArg : null;
args = args.slice(0, args.length - numCBs);
return self.__nativeCall(module, method, args, onFail, onSucc);
};
}
fn.type = type;
return fn;
}
7. __nativeCall实现
function __nativeCall(module, method, params, onFail, onSucc) {
this._queue[MODULE_IDS].push(module);
this._queue[METHOD_IDS].push(method);
this._queue[PARAMS].push(params);
var now = new Date().getTime();
if (global.nativeFlushQueueImmediate &&
now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS) {
global.nativeFlushQueueImmediate(this._queue);
this._queue = [[], [], [], this._callID];
this._lastFlush = now;
}
}
8. JSCExecutor.cpp 通过installGlobalFunction 定义 nativeFlushQueueImmediate方法
m_context = JSGlobalContextCreateInGroup(nullptr, nullptr);
s_globalContextRefToJSCExecutor[m_context] = this;
installGlobalFunction(m_context, "nativeFlushQueueImmediate", nativeFlushQueueImmediate);
installGlobalFunction(m_context, "nativePerformanceNow", nativePerformanceNow);
installGlobalFunction(m_context, "nativeStartWorker", nativeStartWorker);
installGlobalFunction(m_context, "nativePostMessageToWorker", nativePostMessageToWorker);
installGlobalFunction(m_context, "nativeTerminateWorker", nativeTerminateWorker);
installGlobalFunction(m_context, "nativeInjectHMRUpdate", nativeInjectHMRUpdate);
9. nativeFlushQueueImmediate 获取 JS队列数据执行Native调用:
JSValueRef JSCExecutor::nativeFlushQueueImmediate(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception) {
std::string resStr = Value(ctx, arguments[0]).toJSONString();
executor->flushQueueImmediate(resStr);
return JSValueMakeUndefined(ctx);
10. flushQueueImmediate获取JS队列执行队列数据调用Native接口:
void JSCExecutor::flushQueueImmediate(std::string queueJSON) {
m_bridge->callNativeModules(*this, queueJSON, false);
}
11. callNativeModules 调用Native java方法
class BridgeCallback {
public:
virtual ~BridgeCallback() {};
virtual void onCallNativeModules(
ExecutorToken executorToken,
const std::string& callJSON,
bool isEndOfBatch) = 0;
virtual void onExecutorUnregistered(ExecutorToken executorToken) = 0;
};
void Bridge::callNativeModules(JSExecutor& executor, const std::string& callJSON, bool isEndOfBatch) {
m_callback->onCallNativeModules(getTokenForExecutor(executor), callJSON, isEndOfBatch);
}
BridgeCallback::m_callback 为OnLoad.cpp 中的 class PlatformBridgeCallback : public BridgeCallback
virtual void onCallNativeModules(
ExecutorToken executorToken,
const std::string& callJSON,
bool isEndOfBatch) override {
executeCallbackOnCallbackQueueThread([executorToken, callJSON, isEndOfBatch] (ResolvedWeakReference& callback) {
JNIEnv* env = Environment::current();
for (auto& call : react::parseMethodCalls(callJSON)) {
makeJavaCall(env, executorToken, callback, call);
if (env->ExceptionCheck()) {
return;
}
}
if (isEndOfBatch) {
signalBatchComplete(env, callback);
}
});
}
相当于执行 PlatformBridgeCallback.onCallNativeModules,最后调用 makeJavaCall方法调用java方法
OnLoad.cpp 中 makeJavaCall 定义, c++通过CallVoidMethod调用java非静态方法:
static void makeJavaCall(JNIEnv* env, ExecutorToken executorToken, jobject callback, const MethodCall& call) {
auto newArray = ReadableNativeArray::newObjectCxxArgs(std::move(call.arguments));
env->CallVoidMethod(
callback,
gCallbackMethod,
static_cast<JExecutorTokenHolder*>(executorToken.getPlatformExecutorToken().get())->getJobj(),
call.moduleId,
call.methodId,
newArray.get());
}
三. JavaScript调用Native回调和返回值
从编写自定义插件中,我们知道了JS如何调用Native方法,但 @ReactMethod 注解的方法的返回值只能是void,现在JS端想从Native获取一些配置信息或者知道调用端是否成功的一些返回值信息,该如何实现呢?
JavaScript调用Native获取Native返回值是通过异步Callback实现的. 在JS调用Native时,会判断方法的最后两个参数,如果是function,就会把函数放到callback数值中, key为自增的callbackId,同时把callbackId传递给Native。Native执行完以后,通过调用JS方法 __invokeCallback 进行回调。在react-native中定是通过Callback和Promise的接口,用来处理JavaScript调用Java方法的回调,Callback会作为ReactMethod注解方法的一个参数,Native调用JS就是通过这个Callback实现的,具体实现会在下面讲到。
首先,我们看一下Callback和Promise具体实现,然后根据代码来剖析实现原理。
Callback实现
1. java端实现一个需要获取执行结果的setCache和一个获取缓存接口getCache
@ReactMethod
public void setCache(String key, String value, Callback successCallback, Callback errorCallback) {
try {
sharedPreference = getCurrentActivity().getSharedPreferences("rn_cache", 0);
sharedPreference.edit().putString(key, value).commit();
successCallback.invoke("save success");
} catch (Exception e) {
e.printStackTrace();
errorCallback.invoke(e.getMessage());
}
}
@ReactMethod
public void getCache(String key, Callback callback) {
callback.invoke(sharedPreference.getString(key, ""));
}
2. JS定义两个方法,一个设置缓存,一个获取缓存。在JavaScript中,调用这个带有Callback参数的方法如下:
_setCacheClick(){
NativeModules.IntentPackage.setCache('ReactNative','我是来自React Native缓存消息',(msg)=>{
NativeModules.ToastAndroid.show(msg, 3000);
},(error)=>{
NativeModules.ToastAndroid.show(error, 3000);
});
}
_getCacheClick(){
NativeModules.IntentPackage.getCache('ReactNative',(value)=>{
NativeModules.ToastAndroid.show(value, 3000)
});
}
Promise实现
1. 同样java端实现一个需要获取执行结果的setCache和一个获取缓存接口getCache,Callback参数改为Promise
@ReactMethod
public void setCachePromise(String key, String value, Promise promise) {
try {
sharedPreference = getCurrentActivity().getSharedPreferences("rn_cache", 0);
sharedPreference.edit().putString(key, value).commit();
promise.resolve("save success");
} catch (Exception e) {
e.printStackTrace();
promise.resolve(e.getMessage());
}
}
@ReactMethod
public void getCachePromise(String key, Promise promise) {
promise.resolve(sharedPreference.getString(key, ""));
}
2. 同样JS定义两个方法,一个设置缓存,一个获取缓存。在JavaScript中,调用这个带有Callback参数的方法如下:
_setCachePromiseClick(){
NativeModules.IntentPackage.setCache('ReactNative','我是来自React Native缓存消息').then(msg=>{
NativeModules.ToastAndroid.show(msg, 3000);
},error=>{
NativeModules.ToastAndroid.show(error, 3000);
}).
}
_getCachePromiseClick(){
NativeModules.IntentPackage.getCache('ReactNative').then(function(value){
NativeModules.ToastAndroid.show(value, 3000)
});
}
JavaScript调用Native Callback实现原理
1.NativeModulesReactCallback 初始化
private ReactBridge initializeBridge(JavaScriptExecutor jsExecutor) {
bridge = new ReactBridge(
jsExecutor,
new NativeModulesReactCallback(),
mReactQueueConfiguration.getNativeModulesQueueThread());
return bridge;
}
public ReactBridge(
JavaScriptExecutor jsExecutor,
ReactCallback callback,
MessageQueueThread nativeModulesQueueThread) {
mJSExecutor = jsExecutor;
mCallback = callback;
mNativeModulesQueueThread = nativeModulesQueueThread;
initialize(jsExecutor, callback, mNativeModulesQueueThread);
}
2.ReactCallback源码实现:
@DoNotStrip
public interface ReactCallback {
@DoNotStrip
void call(ExecutorToken executorToken, int moduleId, int methodId, ReadableNativeArray parameters);
}
private class NativeModulesReactCallback implements ReactCallback {
@Override
public void call(ExecutorToken executorToken, int moduleId, int methodId, ReadableNativeArray parameters) {
synchronized (mJSToJavaCallsTeardownLock) {
// NativeModuleRegistry调用call
nativeModuleRegistry.call(CatalystInstanceImpl.this, executorToken, moduleId, methodId, parameters);
}
}
}
3.NativeModuleRegistry源码实现:
public class NativeModuleRegistry {
private static class MethodRegistration {
public MethodRegistration(String name, String tracingName, NativeModule.NativeMethod method) {
this.name = name;
this.tracingName = tracingName;
this.method = method;
}
public String name;
public String tracingName;
// Native 模块必须实现的接口NativeModule
public NativeModule.NativeMethod method;
}
}
private static class ModuleDefinition {
public final int id;
public final String name;
public final NativeModule target;
public final ArrayList<MethodRegistration> methods;
public ModuleDefinition(int id, String name, NativeModule target) {
this.id = id;
this.name = name;
this.target = target;
this.methods = new ArrayList<MethodRegistration>();
// target.getMethods() 收集 @ReactMehtod 注解的方法
for (Map.Entry<String, NativeModule.NativeMethod> entry : target.getMethods().entrySet()) {
this.methods.add(
new MethodRegistration(
entry.getKey(), "NativeCall__" + target.getName() + "_" + entry.getKey(),
entry.getValue()));
}
}
public void call(
CatalystInstance catalystInstance,
ExecutorToken executorToken,
int methodId,
ReadableNativeArray parameters) {
// this.methods.get(methodId).method == NativeModule.NativeMethod
this.methods.get(methodId).method.invoke(catalystInstance, executorToken, parameters);
}
}
}
4.我们再来看一下Native自定义模块IntentModule实现
public abstract class BaseJavaModule implements NativeModule {
static final private ArgumentExtractor<Callback> ARGUMENT_EXTRACTOR_CALLBACK =
new ArgumentExtractor<Callback>() {
@Override
public @Nullable Callback extractArgument(
CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
if (jsArguments.isNull(atIndex)) {
return null;
} else {
int id = (int) jsArguments.getDouble(atIndex);
//CallbackImpl 实现 Callback接口
return new CallbackImpl(catalystInstance, executorToken, id);
}
}
};
static final private ArgumentExtractor<Promise> ARGUMENT_EXTRACTOR_PROMISE =
new ArgumentExtractor<Promise>() {
@Override
public int getJSArgumentsNeeded() {
return 2;
}
@Override
public Promise extractArgument(
CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
Callback resolve = ARGUMENT_EXTRACTOR_CALLBACK
.extractArgument(catalystInstance, executorToken, jsArguments, atIndex);
Callback reject = ARGUMENT_EXTRACTOR_CALLBACK
.extractArgument(catalystInstance, executorToken, jsArguments, atIndex + 1);
return new PromiseImpl(resolve, reject);
}
};
private @Nullable Map<String, NativeMethod> mMethods;
private @Nullable Map<String, SyncNativeHook> mHooks;
// getMethods实现
@Override
public final Map<String, NativeMethod> getMethods() {
Method[] targetMethods = getClass().getDeclaredMethods();
for (Method targetMethod : targetMethods) {
if (targetMethod.getAnnotation(ReactMethod.class) != null) {
String methodName = targetMethod.getName();
mMethods.put(methodName, new JavaMethod(targetMethod));
}
if (targetMethod.getAnnotation(ReactSyncHook.class) != null) {
String methodName = targetMethod.getName();
mHooks.put(methodName, new SyncJavaHook(targetMethod));
}
}
return assertNotNull(mMethods);
}
public class JavaMethod implements NativeMethod {
private Method mMethod;
public JavaMethod(Method method) {
mMethod = method;
}
@Override
public void invoke(CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray parameters) {
mMethod.invoke(BaseJavaModule.this, mArguments);
}
}
}
public abstract class ReactContextBaseJavaModule extends BaseJavaModule {
}
public class IntentModule extends ReactContextBaseJavaModule {
}
5.Callback 实现
private native void initialize(
JavaScriptExecutor jsExecutor,
ReactCallback callback,
MessageQueueThread nativeModulesQueueThread);
public final class CallbackImpl implements Callback {
private final CatalystInstance mCatalystInstance;
private final ExecutorToken mExecutorToken;
private final int mCallbackId;
public CallbackImpl(CatalystInstancebridge = new ReactBridge(
jsExecutor,
new NativeModulesReactCallback(),
mReactQueueConfiguration.getNativeModulesQueueThread()); bridge, ExecutorToken executorToken, int callbackId) {
mCatalystInstance = bridge;
mExecutorToken = executorToken;
mCallbackId = callbackId;
}
@Override
public void invoke(Object... args) {
mCatalystInstance.invokeCallback(mExecutorToken, mCallbackId, Arguments.fromJavaArgs(args));
}
}
6.CatalystInstanceImpl类中invokeCallback调用
@Override
public void invokeCallback(ExecutorToken executorToken, int callbackID, NativeArray arguments) {
if (mIsBeingDestroyed) {
FLog.w(ReactConstants.TAG, "Invoking JS callback after bridge has been destroyed.");
return;
}
synchronized (mJavaToJSCallsTeardownLock) {
if (mDestroyed) {
FLog.w(ReactConstants.TAG, "Invoking JS callback after bridge has been destroyed.");
return;
}
incrementPendingJSCalls();
Assertions.assertNotNull(mBridge).invokeCallback(executorToken, callbackID, arguments);
}
}
7.ReactBridge.java中invokeCallback调用
public native void invokeCallback(ExecutorToken executorToken, int callbackID, NativeArray arguments);
8.OnLoad.cpp
static void invokeCallback(JNIEnv* env, jobject obj, JExecutorToken::jhybridobject jExecutorToken, jint callbackId,
NativeArray::jhybridobject args) {
auto bridge = extractRefPtr<CountableBridge>(env, obj);
auto arguments = cthis(wrap_alias(args));
try {
bridge->invokeCallback(
cthis(wrap_alias(jExecutorToken))->getExecutorToken(wrap_alias(jExecutorToken)),
(double) callbackId,
std::move(arguments->array)
);
} catch (...) {
translatePendingCppExceptionToJavaException();
}
}
9.Bridge.cpp实现
void Bridge::invokeCallback(ExecutorToken executorToken, const double callbackId, const folly::dynamic& arguments) {
#ifdef WITH_FBSYSTRACE
int systraceCookie = m_systraceCookie++;
FbSystraceAsyncFlow::begin(
TRACE_TAG_REACT_CXX_BRIDGE,
"<callback>",
systraceCookie);
#endif
#ifdef WITH_FBSYSTRACE
runOnExecutorQueue(executorToken, [callbackId, arguments, systraceCookie] (JSExecutor* executor) {
FbSystraceAsyncFlow::end(
TRACE_TAG_REACT_CXX_BRIDGE,
"<callback>",
systraceCookie);
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "Bridge.invokeCallback");
#else
runOnExecutorQueue(executorToken, [callbackId, arguments] (JSExecutor* executor) {
#endif
executor->invokeCallback(callbackId, arguments);
});
}
10.JSCExecutor.cpp 中invokeCallback实现
void JSCExecutor::invokeCallback(const double callbackId, const folly::dynamic& arguments) {
String argsString = String(folly::toJson(std::move(arguments)).c_str());
JSValueRef args[] = {
JSValueMakeNumber(m_context, callbackId),
Value::fromJSON(m_context, argsString)
};
// m_invokeCallbackObj = folly::make_unique<Object>(m_batchedBridge->getProperty("invokeCallbackAndReturnFlushedQueue").asObject());
// 执行回调,返回待执行的队列
auto result = m_invokeCallbackObj->callAsFunction(2, args);
// 调用java方法
m_bridge->callNativeModules(*this, result.toJSONString(), true);
}
11.JS端invokeCallbackAndReturnFlushedQueue实现
function invokeCallbackAndReturnFlushedQueue(cbID, args) {
var _this3 = this;
guard(function () {
// 执行回调
_this3.__invokeCallback(cbID, args);
_this3.__callImmediates();
});
// 返回JS调用Native的队列
return this.flushedQueue();
}