ReactNative 源码分析8——Native Modules通信机制 之Java调用Js

3 阅读2分钟

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();
  }
}