1.React Native 三大线程
在ReactInstanceManager的createReactContext中生成CatalystInstanceImpl的时候,在builder里面传递里一个ReactQueueConfigurationSpec
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSModuleRegistry(jsModulesBuilder.build())
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
接着看ReactQueueConfigurationSpec.createDefault()这个方法
public static ReactQueueConfigurationSpec createDefault() {
MessageQueueThreadSpec spec = Build.VERSION.SDK_INT < 21 ?
MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules", LEGACY_STACK_SIZE_BYTES) :
MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules");
return builder()
.setJSQueueThreadSpec(MessageQueueThreadSpec.newBackgroundThreadSpec("js"))
.setNativeModulesQueueThreadSpec(spec)
.build();
}
这个方法设定nativeModules和jsModules的MessageQueue的规格,接着执行到CatalystInstanceImpl的构造函数,在里面会执行
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
ReactQueueConfigurationSpec,
new NativeExceptionHandler());
首先看MessageQueueThreadImpl的构造函数
private MessageQueueThreadImpl(
String name,
Looper looper,
QueueThreadExceptionHandler exceptionHandler) {
mName = name;
mLooper = looper;
mHandler = new MessageQueueThreadHandler(looper, exceptionHandler);
mAssertionErrorMessage = "Expected to be called from the '" + getName() + "' thread!";
}
public class MessageQueueThreadHandler extends Handler {
private final QueueThreadExceptionHandler mExceptionHandler;
public MessageQueueThreadHandler(Looper looper, QueueThreadExceptionHandler exceptionHandler) {
super(looper);
mExceptionHandler = exceptionHandler;
}
@Override
public void dispatchMessage(Message msg) {
try {
super.dispatchMessage(msg);
} catch (Exception e) {
mExceptionHandler.handleException(e);
}
}
}
上面的代码就可以看出来,MessageQueueThreadImpl这个其实是实现消息的处理,handler发送和处理消息,looper进行消息循环
public static ReactQueueConfigurationImpl create(
ReactQueueConfigurationSpec spec,
QueueThreadExceptionHandler exceptionHandler) {
Map<MessageQueueThreadSpec, MessageQueueThreadImpl> specsToThreads = MapBuilder.newHashMap();
MessageQueueThreadSpec uiThreadSpec = MessageQueueThreadSpec.mainThreadSpec();
MessageQueueThreadImpl uiThread =
MessageQueueThreadImpl.create( uiThreadSpec, exceptionHandler);
specsToThreads.put(uiThreadSpec, uiThread);
MessageQueueThreadImpl jsThread = specsToThreads.get(spec.getJSQueueThreadSpec());
if (jsThread == null) {
jsThread = MessageQueueThreadImpl.create(spec.getJSQueueThreadSpec(), exceptionHandler);
}
MessageQueueThreadImpl nativeModulesThread =
specsToThreads.get(spec.getNativeModulesQueueThreadSpec());
if (nativeModulesThread == null) {
nativeModulesThread =
MessageQueueThreadImpl.create(spec.getNativeModulesQueueThreadSpec(), exceptionHandler);
}
return new ReactQueueConfigurationImpl(uiThread, nativeModulesThread, jsThread);
}
在这个方法里,首先会构造一个MessageQueueThreadImpl,这个是用来关联ui线程的
/**
* @return a MessageQueueThreadImpl corresponding to Android's main UI thread.
*/
private static MessageQueueThreadImpl createForMainThread(
String name,
QueueThreadExceptionHandler exceptionHandler) {
Looper mainLooper = Looper.getMainLooper();
final MessageQueueThreadImpl mqt =
new MessageQueueThreadImpl(name, mainLooper, exceptionHandler);
if (UiThreadUtil.isOnUiThread()) {
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
MessageQueueThreadRegistry.register(mqt);
} else {
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
MessageQueueThreadRegistry.register(mqt);
}
});
}
return mqt;
}
public static MessageQueueThreadImpl startNewBackgroundThread(
final String name,
long stackSize,
QueueThreadExceptionHandler exceptionHandler) {
final SimpleSettableFuture<Looper> looperFuture = new SimpleSettableFuture<>();
final SimpleSettableFuture<MessageQueueThread> mqtFuture = new SimpleSettableFuture<>();
Thread bgThread = new Thread(null,
new Runnable() {
@Override
public void run() {
Looper.prepare();
looperFuture.set(Looper.myLooper());
MessageQueueThreadRegistry.register(mqtFuture.getOrThrow());
Looper.loop();
}
}, "mqt_" + name, stackSize);
bgThread.start();
Looper myLooper = looperFuture.getOrThrow();
MessageQueueThreadImpl mqt = new MessageQueueThreadImpl(name, myLooper, exceptionHandler);
mqtFuture.set(mqt);
return mqt;
}
在这个方法里面,除了生成MessageQueueThreadImpl,还启动里一个线程bgThread.start()。
综上,ReactNative关联了ui线程,生成native线程与js线程
2.React Native 通信机制
总的来说:JNI作为C++与Java的桥梁,JSC作为C++与JavaScript的桥梁,而C++最终连接了Java与JavaScript。
ReactNative线程处理完毕之后,会调用native的initializeBridge方法将JS线程与Native线程传入到C++层
private native void initializeBridge(
ReactCallback callback,
JavaScriptExecutor jsExecutor,
MessageQueueThread jsQueue,
MessageQueueThread moduleQueue,
Collection<JavaModuleWrapper> javaModules,
Collection<ModuleHolder> cxxModules);
ReactCallback callback:CatalystInstanceImpl的静态内部类ReactCallback,负责接口回调。
JavaScriptExecutor jsExecutor:JS执行器,将JS的调用传递给C++层。
MessageQueueThread jsQueue.getJSQueueThread():JS线程
MessageQueueThread moduleQueue:Native线程
CollectionjavaModules:来源于mJavaRegistry.getJavaModules(this)。
Collection cxxModules:来源于mJavaRegistry.getCxxModules()。
void CatalystInstanceImpl::initializeBridge(
jni::alias_ref<ReactCallback::javaobject> callback,
// This executor is actually a factory holder.
JavaScriptExecutorHolder* jseh,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
jni::alias_ref<JavaMessageQueueThread::javaobject> nativeModulesQueue,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules) {
// TODO mhorowitz: how to assert here?
// Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");
moduleMessageQueue_ = std::make_shared<JMessageQueueThread>(nativeModulesQueue);
// This used to be:
//
// Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> Bridge::Callback
// --weak--> ReactCallback -> Java CatalystInstanceImpl
//
// Now the weak ref is a global ref. So breaking the loop depends on
// CatalystInstanceImpl#destroy() calling mHybridData.resetNative(), which
// should cause all the C++ pointers to be cleaned up (except C++
// CatalystInstanceImpl might be kept alive for a short time by running
// callbacks). This also means that all native calls need to be pre-checked
// to avoid NPE.
// See the comment in callJSFunction. Once js calls switch to strings, we
// don't need jsModuleDescriptions any more, all the way up and down the
// stack.
instance_->initializeBridge(
folly::make_unique<JInstanceCallback>(callback, moduleMessageQueue_),
jseh->getExecutorFactory(),
folly::make_unique<JMessageQueueThread>(jsQueue),
buildModuleRegistry(
std::weak_ptr<Instance>(instance_), javaModules, cxxModules, moduleMessageQueue_));
}
void Instance::initializeBridge(
std::unique_ptr<InstanceCallback> callback,
std::shared_ptr<JSExecutorFactory> jsef,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<ModuleRegistry> moduleRegistry) {
callback_ = std::move(callback);
jsQueue->runOnQueueSync(
[this, &jsef, moduleRegistry, jsQueue] () mutable {
// 生成NativeToJsBridge
nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
jsef.get(), moduleRegistry, jsQueue, callback_);
std::lock_guard<std::mutex> lock(m_syncMutex);
m_syncReady = true;
m_syncCV.notify_all();
});
CHECK(nativeToJsBridge_);
}
在这个方法中,生成了一个NativeToJsBridge,下面看NativeToJsBridge的构造方法
NativeToJsBridge::NativeToJsBridge(
JSExecutorFactory* jsExecutorFactory,
std::shared_ptr<ModuleRegistry> registry,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<InstanceCallback> callback)
: m_destroyed(std::make_shared<bool>(false))
, m_mainExecutorToken(callback->createExecutorToken())
, m_delegate(std::make_shared<JsToNativeBridge>(this, registry, callback)) {
// 生成JSCExecutor,用来执行JS
std::unique_ptr<JSExecutor> mainExecutor =
jsExecutorFactory->createJSExecutor(m_delegate, jsQueue);
// cached to avoid locked map lookup in the common case
m_mainExecutor = mainExecutor.get();
registerExecutor(m_mainExecutorToken, std::move(mainExecutor), jsQueue);
}
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate, std::shared_ptr<MessageQueueThread> jsQueue) {
return std::unique_ptr<JSExecutor>(
new JSCExecutor(delegate, jsQueue, m_cacheDir, m_jscConfig));
}
JSCExecutor::JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> messageQueueThread,
const std::string& cacheDir,
const folly::dynamic& jscConfig) throw(JSException) :
m_delegate(delegate),
m_deviceCacheDir(cacheDir),
m_messageQueueThread(messageQueueThread),
m_nativeModules(delegate ? delegate->getModuleRegistry() : nullptr),
m_jscConfig(jscConfig) {
initOnJSVMThread();
{
SystraceSection s("nativeModuleProxy object");
// 为js里面的global变量设置代码
installGlobalProxy(m_context, "nativeModuleProxy",
exceptionWrapMethod<&JSCExecutor::getNativeModule>());
}
}
在这个代码里,首先生成JsToNativeBridge(JS调用Java的桥梁),接着生成JSCExecutor,用来执行js,走到这一步,JsToNativeBridge(JS调用Java的桥梁),NativeToJsBridge(Java调用JS的桥梁)等相关的类已经都生成了。
在C++层的Executor.h文件中定义了整个Java调用JS,JS调用Java的逻辑。
Executor.h文件中定义了抽象类ExecutorDelegate,定义了执行Native Module的方法,它是JS调用Java的桥梁,JsToNativeBridge实现了该类的纯虚函数(抽象方法),该抽象类还持有JSExecutor(用来执行JS)的引用。
Executor.h文件中定义了抽象类JSExecutor,它定义了执行JS Module的方法,用来解释执行JS,JSCExecutor实现了该类中的纯虚函数(抽象方法),另一个类 NativeToBridge与JsToNativeBridge相对应,它是Java调用JS的桥梁,NativeToBridge持有JSCExecutor的引用,如果NativeToBridge需要执行JS时就会 去调用JSCExecutor。
a.js调用java代码
自定义原生模块的调用可以查看这个例子:https://reactnative.cn/docs/0.51/native-modules-android.html#content
可以看到js调用java代码的时候都是用NativeModules.xxxModule.xxxMethod()
let NativeModules : {[moduleName: string]: Object} = {};
if (global.nativeModuleProxy) {
NativeModules = global.nativeModuleProxy;
} else {
const bridgeConfig = global.__fbBatchedBridgeConfig;
invariant(bridgeConfig, '__fbBatchedBridgeConfig is not set, cannot invoke native modules');
const defineLazyObjectProperty = require('defineLazyObjectProperty');
(bridgeConfig.remoteModuleConfig || []).forEach((config: ModuleConfig, moduleID: number) => {
// Initially this config will only contain the module name when running in JSC. The actual
// configuration of the module will be lazily loaded.
const info = genModule(config, moduleID);
if (!info) {
return;
}
if (info.module) {
NativeModules[info.name] = info.module;
}
// If there's no module config, define a lazy getter
else {
defineLazyObjectProperty(NativeModules, info.name, {
get: () => loadModule(info.name, moduleID)
});
}
});
}
module.exports = NativeModules;
nativeModuleProxy实质上是在启动流程中,JSCExecutor::JSCExecutor()在创建时通过installGlobalProxy(m_context, “nativeModuleProxy”, exceptionWrapMethod<&JSCExecutor::getNativeModule>()) 创建的,所以当JS调用NativeModules时,实际上在调用JSCExecutor::getNativeModule()方法
JSValueRef JSCExecutor::getNativeModule(JSObjectRef object, JSStringRef propertyName) {
if (JSC_JSStringIsEqualToUTF8CString(m_context, propertyName, "name")) {
return Value(m_context, String(m_context, "NativeModules"));
}
return m_nativeModules.getModule(m_context, propertyName);
}
接着会执行到JSCNativeModules::getModule方法
JSValueRef JSCNativeModules::getModule(JSContextRef context, JSStringRef jsName) {
if (!m_moduleRegistry) {
return Value::makeUndefined(context);
}
std::string moduleName = String::ref(context, jsName).str();
const auto it = m_objects.find(moduleName);
if (it != m_objects.end()) {
return static_cast<JSObjectRef>(it->second);
}
auto module = createModule(moduleName, context);
if (!module.hasValue()) {
return Value::makeUndefined(context);
}
// Protect since we'll be holding on to this value, even though JS may not
module->makeProtected();
auto result = m_objects.emplace(std::move(moduleName), std::move(*module)).first;
return static_cast<JSObjectRef>(result->second);
}
接着会执行到createModule(moduleName, context)
folly::Optional<Object> JSCNativeModules::createModule(const std::string& name, JSContextRef context) {
if (!m_genNativeModuleJS) {
auto global = Object::getGlobalObject(context);
//获取NativeModules.js里面的genModule方法(global.__fbGenNativeModule = genModule)
m_genNativeModuleJS = global.getProperty("__fbGenNativeModule").asObject();
m_genNativeModuleJS->makeProtected();
// Initialize the module name list, otherwise getModuleConfig won't work
// TODO (pieterdb): fix this in ModuleRegistry
m_moduleRegistry->moduleNames();
}
// 获取js所要调用的java层的方法的配置表
auto result = m_moduleRegistry->getConfig(name);
if (!result.hasValue()) {
return nullptr;
}
// 调用NativeModules.js里面的genModule方法
Value moduleInfo = m_genNativeModuleJS->callAsFunction({
Value::fromDynamic(context, result->config),
Value::makeNumber(context, result->index)
});
CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null";
return moduleInfo.asObject().getProperty("module").asObject();
}
function genMethod(moduleID: number, methodID: number, type: MethodType) {
let fn = null;
if (type === 'promise') {
fn = function(...args: Array<any>) {
return new Promise((resolve, reject) => {
BatchedBridge.enqueueNativeCall(moduleID, methodID, args,
(data) => resolve(data),
(errorData) => reject(createErrorFromErrorData(errorData)));
});
};
} else if (type === 'sync') {
fn = function(...args: Array<any>) {
return global.nativeCallSyncHook(moduleID, methodID, args);
};
} else {
fn = function(...args: Array<any>) {
const lastArg = args.length > 0 ? args[args.length - 1] : null;
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
const hasSuccessCallback = typeof lastArg === 'function';
const hasErrorCallback = typeof secondLastArg === 'function';
hasErrorCallback && invariant(
hasSuccessCallback,
'Cannot have a non-function arg after a function arg.'
);
const onSuccess = hasSuccessCallback ? lastArg : null;
const onFail = hasErrorCallback ? secondLastArg : null;
const callbackCount = hasSuccessCallback + hasErrorCallback;
args = args.slice(0, args.length - callbackCount);
BatchedBridge.enqueueNativeCall(moduleID, methodID, args, onFail, onSuccess);
};
}
fn.type = type;
return fn;
}
这个方法最后会调用BatchedBridge.enqueueNativeCall()方法,看BatchedBridge可以看出这个实际是调用BMessageQueue.enqueueNativeCall()
enqueueNativeCall(
moduleID: number,
methodID: number,
params: any[],
onFail: ?Function,
onSucc: ?Function,
) {
if (onFail || onSucc) {
if (__DEV__) {
this._debugInfo[this._callID] = [moduleID, methodID];
if (this._callID > DEBUG_INFO_LIMIT) {
delete this._debugInfo[this._callID - DEBUG_INFO_LIMIT];
}
}
// Encode callIDs into pairs of callback identifiers by shifting left and using the rightmost bit
// to indicate fail (0) or success (1)
// eslint-disable-next-line no-bitwise
onFail && params.push(this._callID << 1);
// eslint-disable-next-line no-bitwise
onSucc && params.push((this._callID << 1) | 1);
this._successCallbacks[this._callID] = onSucc;
this._failureCallbacks[this._callID] = onFail;
}
if (__DEV__) {
global.nativeTraceBeginAsyncFlow &&
global.nativeTraceBeginAsyncFlow(
TRACE_TAG_REACT_APPS,
'native',
this._callID,
);
}
this._callID++;
this._queue[MODULE_IDS].push(moduleID);
this._queue[METHOD_IDS].push(methodID);
if (__DEV__) {
// Validate that parameters passed over the bridge are
// folly-convertible. As a special case, if a prop value is a
// function it is permitted here, and special-cased in the
// conversion.
const isValidArgument = val => {
const t = typeof val;
if (
t === 'undefined' ||
t === 'null' ||
t === 'boolean' ||
t === 'number' ||
t === 'string'
) {
return true;
}
if (t === 'function' || t !== 'object') {
return false;
}
if (Array.isArray(val)) {
return val.every(isValidArgument);
}
for (const k in val) {
if (typeof val[k] !== 'function' && !isValidArgument(val[k])) {
return false;
}
}
return true;
};
invariant(
isValidArgument(params),
'%s is not usable as a native method argument',
params,
);
// The params object should not be mutated after being queued
deepFreezeAndThrowOnMutationInDev((params: any));
}
this._queue[PARAMS].push(params);
const now = new Date().getTime();
if (
global.nativeFlushQueueImmediate &&
(now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS ||
this._inCall === 0)
) {
var queue = this._queue;
this._queue = [[], [], [], this._callID];
this._lastFlush = now;
global.nativeFlushQueueImmediate(queue);
}
Systrace.counterEvent('pending_js_to_native_queue', this._queue[0].length);
if (__DEV__ && this.__spy && isFinite(moduleID)) {
this.__spy({
type: TO_NATIVE,
module: this._remoteModuleTable[moduleID],
method: this._remoteMethodTable[moduleID][methodID],
args: params,
});
} else if (this.__spy) {
this.__spy({
type: TO_NATIVE,
module: moduleID + '',
method: methodID,
args: params,
});
}
}
这个方法首先将把对应的moduleId,methodId和params push到queue中,接着会去判断两次调用的时差,如果大于MIN_TIME_BETWEEN_FLUSHES_MS(5ms)的话,会调用global.nativeFlushQueueImmediate(this._queue);这个方法去主动把数据传递到C层的。也就是说,如果你两次的通信时间很短,小于5ms,等待native调用js,然后把MessageQueue中的数据发送到C层再通过jni转到java层。接着就会执行到JSCExecutor::nativeFlushQueueImmediate(size_t argumentCount, const JSValueRef arguments[])
JSValueRef JSCExecutor::nativeFlushQueueImmediate(
size_t argumentCount,
const JSValueRef arguments[]) {
if (argumentCount != 1) {
throw std::invalid_argument("Got wrong number of args");
}
flushQueueImmediate(Value(m_context, arguments[0]));
return Value::makeUndefined(m_context);
}
void JSCExecutor::flushQueueImmediate(Value&& queue) {
auto queueStr = queue.toJSONString();
m_delegate->callNativeModules(*this, folly::parseJson(queueStr), false);
}
接着会执行到JsToNativeBridge.callNativeModules()
void callNativeModules(
JSExecutor& executor, folly::dynamic&& calls, bool isEndOfBatch) override {
CHECK(m_registry || calls.empty()) <<
"native module calls cannot be completed with no native modules";
ExecutorToken token = m_nativeToJs->getTokenForExecutor(executor);
m_batchHadNativeModuleCalls = m_batchHadNativeModuleCalls || !calls.empty();
// An exception anywhere in here stops processing of the batch. This
// was the behavior of the Android bridge, and since exception handling
// terminates the whole bridge, there's not much point in continuing.
for (auto& call : parseMethodCalls(std::move(calls))) {
m_registry->callNativeMethod(
token, call.moduleId, call.methodId, std::move(call.arguments), call.callId);
}
if (isEndOfBatch) {
// onBatchComplete will be called on the native (module) queue, but
// decrementPendingJSCalls will be called sync. Be aware that the bridge may still
// be processing native calls when the birdge idle signaler fires.
if (m_batchHadNativeModuleCalls) {
m_callback->onBatchComplete();
m_batchHadNativeModuleCalls = false;
}
m_callback->decrementPendingJSCalls();
}
}
该方法中取出JS队列中的JS调用Java的所有方法,并通过ModuleRegistry::callNativeMethod()方法去遍历调用
void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId, unsigned int methodId,
folly::dynamic&& params, int callId) {
if (moduleId >= modules_.size()) {
throw std::runtime_error(
folly::to<std::string>("moduleId ", moduleId,
" out of range [0..", modules_.size(), ")"));
}
#ifdef WITH_FBSYSTRACE
if (callId != -1) {
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
}
#endif
//modules_是创建ModuleRegistryHolder时根据Java层ModuleRegistryHolder创建的C++ NativeModule
//moduleId为模块在当前列表的索引值
modules_[moduleId]->invoke(token, methodId, std::move(params));
}
class JavaNativeModule : public NativeModule {
void JavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
//wrapper_-的类型是JavaModuleWrapper.cpp,映射Java层的JavaModuleWrapper.java,在ModuleRegistryHolder.cpp构造方法中由Java传入的Java Module被C++包装成
//JavaModuleWrapper对象。通过反射调用Java层的JavaModuleWrapper.java的invoke()方法,同时把mothodId和参数传过去。
static auto invokeMethod =
wrapper_->getClass()->getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast<jint>(reactMethodId),
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
}
}
接着会调用到Java层中,通过反射调用ReactContextBaseJavaModule中的代码
@DoNotStrip
public class JavaModuleWrapper {
@DoNotStrip
public void invoke(ExecutorToken token, int methodId, ReadableNativeArray parameters) {
if (mMethods == null || methodId >= mMethods.size()) {
return;
}
mMethods.get(methodId).invoke(mJSInstance, token, parameters);
}
}
==++总结++==
1.js调用java代码是从NativeModules.xxxModule.xxxMethod()
2.JSCExecutor::getNativeModule>()获取js所要调用的java层的方法的配置表
3.NativeModules.js根据得到的配置表调用BatchedBridge.enqueueNativeCall(),将module:moduleID, methodID, params等参数传递到c层
4.c层遍历获取对应moduleId的javamoudlewrapper,通过反射调用ReactContextBaseJavaModule中的代码
b.java调用js代码
在rn启动流程中,java层调用js的代码:catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
首先看一下AppRegistry
/**
* JS module interface - main entry point for launching React application for a given key.
*/
public interface AppRegistry extends JavaScriptModule {
void runApplication(String appKey, WritableMap appParameters);
void unmountApplicationComponentAtRootTag(int rootNodeTag);
void startHeadlessTask(int taskId, String taskKey, WritableMap data);
}
在CoreModulesPackage里面注册JavaScriptModule
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
List<Class<? extends JavaScriptModule>> jsModules = new ArrayList<>(Arrays.asList(
DeviceEventManagerModule.RCTDeviceEventEmitter.class,
JSTimersExecution.class,
RCTEventEmitter.class,
RCTNativeAppEventEmitter.class,
AppRegistry.class,
com.facebook.react.bridge.Systrace.class,
HMRClient.class));
if (ReactBuildConfig.DEBUG) {
jsModules.add(DebugComponentOwnershipModule.RCTDebugComponentOwnership.class);
jsModules.add(JSCHeapCapture.HeapCapture.class);
jsModules.add(JSCSamplingProfiler.SamplingProfiler.class);
}
return jsModules;
}
在生成catalystInstance的时候调用processPackage(
ReactPackage reactPackage,
NativeModuleRegistryBuilder nativeModuleRegistryBuilder,
JavaScriptModuleRegistry.Builder jsModulesBuilder) 将这些js模块添加到JavaScriptModuleRegistry中。
catalystInstance.getJSModule(AppRegistry.class)最终会调用JavaScriptModuleRegistry.getJavaScriptModule
public synchronized <T extends JavaScriptModule> T getJavaScriptModule(
CatalystInstance instance,
ExecutorToken executorToken,
Class<T> moduleInterface) {
HashMap<Class<? extends JavaScriptModule>, JavaScriptModule> instancesForContext =
mModuleInstances.get(executorToken);
if (instancesForContext == null) {
instancesForContext = new HashMap<>();
mModuleInstances.put(executorToken, instancesForContext);
}
JavaScriptModule module = instancesForContext.get(moduleInterface);
if (module != null) {
return (T) module;
}
JavaScriptModuleRegistration registration =
Assertions.assertNotNull(
mModuleRegistrations.get(moduleInterface),
"JS module " + moduleInterface.getSimpleName() + " hasn't been registered!");
JavaScriptModule interfaceProxy = (JavaScriptModule) Proxy.newProxyInstance(
moduleInterface.getClassLoader(),
new Class[]{moduleInterface},
new JavaScriptModuleInvocationHandler(executorToken, instance, registration));
instancesForContext.put(moduleInterface, interfaceProxy);
return (T) interfaceProxy;
}
private static class JavaScriptModuleInvocationHandler implements InvocationHandler {
private final WeakReference<ExecutorToken> mExecutorToken;
private final CatalystInstance mCatalystInstance;
private final JavaScriptModuleRegistration mModuleRegistration;
public JavaScriptModuleInvocationHandler(
ExecutorToken executorToken,
CatalystInstance catalystInstance,
JavaScriptModuleRegistration moduleRegistration) {
mExecutorToken = new WeakReference<>(executorToken);
mCatalystInstance = catalystInstance;
mModuleRegistration = moduleRegistration;
}
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
ExecutorToken executorToken = mExecutorToken.get();
if (executorToken == null) {
FLog.w(ReactConstants.TAG, "Dropping JS call, ExecutorToken went away...");
return null;
}
NativeArray jsArgs = args != null ? Arguments.fromJavaArgs(args) : new WritableNativeArray();
mCatalystInstance.callFunction(
executorToken,
mModuleRegistration.getName(),
method.getName(),
jsArgs
);
return null;
}
}
在JavaScriptModuleRegistry通过动态代理的方式获取JavaScriptModule,JavaScriptModuleInvocationHandler.invoke()方法获取了moduleID,methodID,并去调用CatalystInstanceImpl.callFunction();
@Override
public void callFunction(
ExecutorToken executorToken,
final String module,
final String method,
final NativeArray arguments) {
if (mDestroyed) {
FLog.w(ReactConstants.TAG, "Calling JS function after bridge has been destroyed.");
return;
}
if (!mAcceptCalls) {
// Most of the time the instance is initialized and we don't need to acquire the lock
synchronized (mJSCallsPendingInitLock) {
if (!mAcceptCalls) {
mJSCallsPendingInit.add(new PendingJSCall(executorToken, module, method, arguments));
return;
}
}
}
jniCallJSFunction(executorToken, module, method, arguments);
}
private native void jniCallJSCallback(ExecutorToken executorToken, int callbackID, NativeArray arguments);
下面就进入到CatalystInstanceImpl.cpp
void CatalystInstanceImpl::jniCallJSFunction(
JExecutorToken* token, std::string module, std::string method, NativeArray* arguments) {
// We want to share the C++ code, and on iOS, modules pass module/method
// names as strings all the way through to JS, and there's no way to do
// string -> id mapping on the objc side. So on Android, we convert the
// number to a string, here which gets passed as-is to JS. There, they they
// used as ids if isFinite(), which handles this case, and looked up as
// strings otherwise. Eventually, we'll probably want to modify the stack
// from the JS proxy through here to use strings, too.
instance_->callJSFunction(token->getExecutorToken(nullptr),
std::move(module),
std::move(method),
arguments->consume());
}
接着就执行到了Instance.cpp的callJSFunction方法
void Instance::callJSFunction(ExecutorToken token, std::string&& module, std::string&& method,
folly::dynamic&& params) {
callback_->incrementPendingJSCalls();
nativeToJsBridge_->callFunction(token, std::move(module), std::move(method), std::move(params));
}
接着会调用NativeToJsBridge.callFunction
void NativeToJsBridge::callFunction(
ExecutorToken executorToken,
std::string&& module,
std::string&& method,
folly::dynamic&& arguments) {
int systraceCookie = -1;
#ifdef WITH_FBSYSTRACE
systraceCookie = m_systraceCookie++;
std::string tracingName = fbsystrace_is_tracing(TRACE_TAG_REACT_CXX_BRIDGE) ?
folly::to<std::string>("JSCall__", module, '_', method) : std::string();
SystraceSection s(tracingName.c_str());
FbSystraceAsyncFlow::begin(
TRACE_TAG_REACT_CXX_BRIDGE,
tracingName.c_str(),
systraceCookie);
#else
std::string tracingName;
#endif
runOnExecutorQueue(executorToken, [module = std::move(module), method = std::move(method), arguments = std::move(arguments), tracingName = std::move(tracingName), systraceCookie] (JSExecutor* executor) {
#ifdef WITH_FBSYSTRACE
FbSystraceAsyncFlow::end(
TRACE_TAG_REACT_CXX_BRIDGE,
tracingName.c_str(),
systraceCookie);
SystraceSection s(tracingName.c_str());
#endif
// This is safe because we are running on the executor's thread: it won't
// destruct until after it's been unregistered (which we check above) and
// that will happen on this thread
executor->callFunction(module, method, arguments);
});
}
void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) {
SystraceSection s("JSCExecutor::callFunction");
// This weird pattern is because Value is not default constructible.
// The lambda is inlined, so there's no overhead.
auto result = [&] {
try {
// See flush()
CHECK(m_callFunctionReturnFlushedQueueJS)
<< "Attempting to call native methods without loading BatchedBridge.js";
return m_callFunctionReturnFlushedQueueJS->callAsFunction({
Value(m_context, String::createExpectingAscii(m_context, moduleId)),
Value(m_context, String::createExpectingAscii(m_context, methodId)),
Value::fromDynamic(m_context, std::move(arguments))
});
} catch (...) {
std::throw_with_nested(
std::runtime_error("Error calling " + moduleId + "." + methodId));
}
}();
//将调用结果返回给Java层
callNativeModules(std::move(result));
}
m_callFunctionReturnFlushedQueueJS->callAsFunction会执行到js里面去,调用MessageQueue.callFunctionReturnFlushedQueue()
callFunctionReturnFlushedQueue(module: string, method: string, args: Array<any>) {
guard(() => {
this.__callFunction(module, method, args);
this.__callImmediates();
});
return this.flushedQueue();
}
__callFunction(module: string, method: string, args: Array<any>) {
this._lastFlush = new Date().getTime();
this._eventLoopStartTime = this._lastFlush;
Systrace.beginEvent(`${module}.${method}()`);
if (this.__spy) {
this.__spy({ type: TO_JS, module, method, args});
}
//JavaScriptModule注册表中查找到对应的module
const moduleMethods = this._callableModules[module];
invariant(
!!moduleMethods,
'Module %s is not a registered callable module (calling %s)',
module, method
);
invariant(
!!moduleMethods[method],
'Method %s does not exist on module %s',
method, module
);
// 执行js获取返回值
const result = moduleMethods[method].apply(moduleMethods, args);
Systrace.endEvent();
return result;
}
这样的话,整个一个java调用js便执行完毕