在 React Native App中凑懂,在應用啟動時根據(jù) ReactPackage 會自動生成 JavaScriptModuleRegistry和NativeModuleRegistry兩份模塊配置表,包含系統(tǒng)CoreModulesPackage, 基礎模塊MainReactPackage以及自定義模塊枚荣。Java端與JavaScript端持有相同的模塊配置表困食,標識為可識別為Native模塊或JavaScript模塊都是通過實現(xiàn)相應接口边翁,并將實例添加ReactPackage的CreactModules方法即可。
一. Native啟動React Application
JavaScript模塊extends JavascriptModule, JavaScript模塊通過java動態(tài)代理實現(xiàn)調(diào)用Js模塊硕盹。下例 AppRegistry.java 為在加載完 Jsbundle 后符匾,Native 去啟動 React Application 的總入口,appkey 為應用的 ID瘩例。映射每個 JavascriptModule 的信息保存在 JavaScriptModuleRegistration 中啊胶,統(tǒng)一由 JavaScriptModuleRegistry統(tǒng)一管理甸各。
1. setupReactContext
ReactInstanceManagerImpl.java 中 ReactContextInitAsyncTask.setupReactContext() 方法中如下調(diào)用:
((AppRegistry)catalystInstance.getJSModule(AppRegistry.class)).runApplication(appkey, appParams);
2. Java動態(tài)代理
JS模塊通過java動態(tài)代理實現(xiàn)調(diào)用JS方法,java動態(tài)代理通過實現(xiàn)InvocationHandler接口,然后通過Proxy.newProxyInstance()實現(xiàn). 方法有三個參數(shù):
類加載器(Class Loader)
需要實現(xiàn)的接口數(shù)組
所有動態(tài)代理類的方法調(diào)用焰坪,都會交由InvocationHandler接口實現(xiàn)類里的invoke()方法去處理趣倾。這是動態(tài)代理的關鍵所在。
(JavaScriptModule)Proxy.newProxyInstance(moduleInterface.getClassLoader(), new Class[]{moduleInterface},
new JavaScriptModuleRegistry.JavaScriptModuleInvocationHandler(executorToken, instance, registration));
3.JavaScript模塊:繼承JavascriptModule實現(xiàn)自定義JavaScript模塊某饰。
public interface AppRegistry extends JavaScriptModule {
void runApplication(String appKey, WritableMap appParameters);
void unmountApplicationComponentAtRootTag(int rootNodeTag);
}
4.實現(xiàn) InvocationHandler接口儒恋,實現(xiàn)invoke方法,invoke 調(diào)用 callFunction實現(xiàn)js的調(diào)用黔漂。
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調(diào)用流程詳細流程:
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()
// 執(zhí)行fbBatchedBridge中js方法
3. void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) {
4. 執(zhí)行js fbBatchedBridge.callFunctionReturnFlushedQueue 返回queue隊列
5. 執(zhí)行Bridge.cpp : void Bridge::callNativeModules(JSExecutor& executor, const std::string& callJSON, bool isEndOfBatch)
6. 執(zhí)行 m_callback->onCallNativeModules(getTokenForExecutor(executor), callJSON, isEndOfBatch);
m_callback 為OnLoad.cpp 中的 class PlatformBridgeCallback : public BridgeCallback
相當于執(zhí)行 PlatformBridgeCallback.onCallNativeModules
7. 最后調(diào)用 makeJavaCall方法調(diào)用java方法
8. OnLoad.cpp 中 makeJavaCall 定義, c++通過CallVoidMethod調(diào)用java非靜態(tài)方法:
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調(diào)用:
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調(diào)用Native模塊
var modules = this._genModules(modulesConfig);
return modules;
});
}
2. Bridge全局配置表
__fbBatchedBridgeConfig 由Native層注入的全局對象,數(shù)據(jù)格式如下,包含remoteModuleConfig節(jié)點炬守。節(jié)點信息包括: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實現(xiàn)
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 調(diào)用 _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 調(diào)用 _genMethod
function _genModule(config, moduleID) {
module[methodName] = _this6._genMethod(moduleID, methodID, methodType);
return { name: moduleName, module: module };
}
6. _genMethod 調(diào)用 __nativeCall 返回 Promise或function
function _genMethod 調(diào)用 (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實現(xiàn)
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隊列數(shù)據(jù)執(zhí)行Native調(diào)用:
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隊列執(zhí)行隊列數(shù)據(jù)調(diào)用Native接口:
void JSCExecutor::flushQueueImmediate(std::string queueJSON) {
m_bridge->callNativeModules(*this, queueJSON, false);
}
11. callNativeModules 調(diào)用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);
}
});
}
相當于執(zhí)行 PlatformBridgeCallback.onCallNativeModules,最后調(diào)用 makeJavaCall方法調(diào)用java方法
OnLoad.cpp 中 makeJavaCall 定義, c++通過CallVoidMethod調(diào)用java非靜態(tài)方法:
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調(diào)用Native回調(diào)和返回值
從編寫自定義插件中劳较,我們知道了JS如何調(diào)用Native方法驹止,但 @ReactMethod 注解的方法的返回值只能是void,現(xiàn)在JS端想從Native獲取一些配置信息或者知道調(diào)用端是否成功的一些返回值信息观蜗,該如何實現(xiàn)呢?
JavaScript調(diào)用Native獲取Native返回值是通過異步Callback實現(xiàn)的. 在JS調(diào)用Native時衣洁,會判斷方法的最后兩個參數(shù)墓捻,如果是function,就會把函數(shù)放到callback數(shù)值中, key為自增的callbackId坊夫,同時把callbackId傳遞給Native砖第。Native執(zhí)行完以后,通過調(diào)用JS方法 __invokeCallback 進行回調(diào)环凿。在react-native中定是通過Callback和Promise的接口梧兼,用來處理JavaScript調(diào)用Java方法的回調(diào),Callback會作為ReactMethod注解方法的一個參數(shù)智听,Native調(diào)用JS就是通過這個Callback實現(xiàn)的羽杰,具體實現(xiàn)會在下面講到。
首先到推,我們看一下Callback和Promise具體實現(xiàn)考赛,然后根據(jù)代碼來剖析實現(xiàn)原理。
Callback實現(xiàn)
1. java端實現(xiàn)一個需要獲取執(zhí)行結果的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中捣卤,調(diào)用這個帶有Callback參數(shù)的方法如下:
_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實現(xiàn)
1. 同樣java端實現(xiàn)一個需要獲取執(zhí)行結果的setCache和一個獲取緩存接口getCache忍抽,Callback參數(shù)改為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中干跛,調(diào)用這個帶有Callback參數(shù)的方法如下:
_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調(diào)用Native Callback實現(xiàn)原理
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源碼實現(xiàn):
@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調(diào)用call
nativeModuleRegistry.call(CatalystInstanceImpl.this, executorToken, moduleId, methodId, parameters);
}
}
}
3.NativeModuleRegistry源碼實現(xiàn):
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 模塊必須實現(xiàn)的接口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實現(xiàn)
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 實現(xiàn) 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實現(xiàn)
@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 實現(xiàn)
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調(diào)用
@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調(diào)用
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實現(xiàn)
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實現(xiàn)
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());
// 執(zhí)行回調(diào),返回待執(zhí)行的隊列
auto result = m_invokeCallbackObj->callAsFunction(2, args);
// 調(diào)用java方法
m_bridge->callNativeModules(*this, result.toJSONString(), true);
}
11.JS端invokeCallbackAndReturnFlushedQueue實現(xiàn)
function invokeCallbackAndReturnFlushedQueue(cbID, args) {
var _this3 = this;
guard(function () {
// 執(zhí)行回調(diào)
_this3.__invokeCallback(cbID, args);
_this3.__callImmediates();
});
// 返回JS調(diào)用Native的隊列
return this.flushedQueue();
}