Java调用Js大致有下面 三种场景:
- RN应用启动,在前面的文章中已经分析过了
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
- 事件通知,和RN应用启动异曲同工
//它的底层也是调用this.mCatalystInstance.getJSModule(jsInterface))
ReactApplicationContext.getJSModule<DeviceEventManagerModule.RCTDeviceEventEmitter?>(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
?.emit(eventName, params)
- Js异步调用Java后,通过Promise或Callback返回数据
异步返回数据
Callback的实现是CallbackImpl,注意这里的mCallbackId,它会传递到Js调用Java传递过来的,返回数据时需要回传回去,这样Js才能找到对应的的回调
@Override
public void invoke(Object... args) {
...
mJSInstance.invokeCallback(mCallbackId, Arguments.fromJavaArgs(args));
mInvoked = true;
}
最终调用CatalystInstanceImpl.jniCallJSCallback,它是native方法
private native void jniCallJSCallback(int callbackID, NativeArray arguments);
Promise的实现是PromiseImpl
private @Nullable Callback mResolve;
private @Nullable Callback mReject;
@Override
public void resolve(Object value) {
if (mResolve != null) {
mResolve.invoke(value);
mResolve = null;
mReject = null;
}
}
它最终调用到CallbackImpl.invoke,所以我们继续jniCallJSCallback
CatalystInstanceImpl::jniCallJSCallback
instance_->callJSCallback
nativeToJsBridge_->invokeCallback
executor->invokeCallback
executor是JSIExecutor
- bindBridge在前面的文章已经分析过了
- 调用invokeCallbackAndReturnFlushedQueue_方法
void JSIExecutor::invokeCallback(
const double callbackId,
const folly::dynamic& arguments) {
if (!invokeCallbackAndReturnFlushedQueue_) {
bindBridge();
}
Value ret;
try {
ret = invokeCallbackAndReturnFlushedQueue_->call(
*runtime_, callbackId, valueFromDynamic(*runtime_, arguments));
} catch (...) {
std::throw_with_nested(std::runtime_error(
folly::to<std::string>( "Error invoking callback " , callbackId)));
}
callNativeModules(ret, true);
}
invokeCallbackAndReturnFlushedQueue是MessageQueue的方法
invokeCallbackAndReturnFlushedQueue(
cbID: number,
args: mixed[],
): null | [Array<number>, Array<number>, Array<mixed>, number] {
this.__guard(() => {
this.__invokeCallback(cbID, args);
});
return this.flushedQueue();
}
__invokeCallback的代码很简单
- 通过cbID(就是Java层的mCallbackId)找到回调callback,_successCallbacks和_failureCallbacks是在Js发起调用时processCallbacks函数中被保存的,processCallbacks中还分配了_callID(对应Java层的mCallbackId),下面这个三个变量其实是同一个值
Js调用分配_callID --> Java层mCallbackId -> 返回数据到Js层cbID
- 然后调用callback
__invokeCallback(cbID: number, args: mixed[]): void {
this._lastFlush = Date.now();
this._eventLoopStartTime = this._lastFlush;
const callID = cbID >>> 1;
// eslint-disable-next-line no-bitwise
const isSuccess = cbID & 1;
const callback = isSuccess
? this._successCallbacks.get(callID)
: this._failureCallbacks.get(callID);
...
try {
if (!callback) {
return;
}
this._successCallbacks.delete(callID);
this._failureCallbacks.delete(callID);
callback(...args);
} finally {
}
}
事件通知
在这篇文章了《React Native 源码分析5——ReactActivity之启动RN应用》详细分了启动调用流程
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
因此对于事件通知它最终调用到RCTDeviceEventEmitter.js的emit方法中然后进行事件分发
class RCTDeviceEventEmitter extends EventEmitter<RCTDeviceEventDefinitions> {
// Add systrace to RCTDeviceEventEmitter.emit method for debugging
emit<TEvent: $Keys<RCTDeviceEventDefinitions>>(
eventType: TEvent,
...args: RCTDeviceEventDefinitions[TEvent]
): void {
beginEvent(() => `RCTDeviceEventEmitter.emit#${eventType}`);
super.emit(eventType, ...args);
endEvent();
}
}