React Native Android源碼解讀和交互原理分析

在 React Native App中凑懂,在應用啟動時根據(jù) ReactPackage 會自動生成 JavaScriptModuleRegistry和NativeModuleRegistry兩份模塊配置表,包含系統(tǒng)CoreModulesPackage, 基礎模塊MainReactPackage以及自定義模塊枚荣。Java端與JavaScript端持有相同的模塊配置表困食,標識為可識別為Native模塊或JavaScript模塊都是通過實現(xiàn)相應接口边翁,并將實例添加ReactPackage的CreactModules方法即可。

一. Native啟動React Application

image

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啟動流程

image

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)和返回值

image

從編寫自定義插件中劳较,我們知道了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();
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锈锤,隨后出現(xiàn)的幾起案子驯鳖,更是在濱河造成了極大的恐慌,老刑警劉巖久免,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浅辙,死亡現(xiàn)場離奇詭異,居然都是意外死亡阎姥,警方通過查閱死者的電腦和手機记舆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呼巴,“玉大人泽腮,你說我怎么就攤上這事∫赂希” “怎么了诊赊?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長府瞄。 經(jīng)常有香客問我碧磅,道長,這世上最難降的妖魔是什么遵馆? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任鲸郊,我火速辦了婚禮,結果婚禮上货邓,老公的妹妹穿的比我還像新娘秆撮。我一直安慰自己,他們只是感情好换况,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布职辨。 她就那樣靜靜地躺著,像睡著了一般复隆。 火紅的嫁衣襯著肌膚如雪拨匆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天挽拂,我揣著相機與錄音惭每,去河邊找鬼。 笑死,一個胖子當著我的面吹牛台腥,可吹牛的內(nèi)容都是我干的宏赘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼黎侈,長吁一口氣:“原來是場噩夢啊……” “哼察署!你這毒婦竟也來了?” 一聲冷哼從身側響起峻汉,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤贴汪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后休吠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扳埂,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年瘤礁,在試婚紗的時候發(fā)現(xiàn)自己被綠了阳懂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡柜思,死狀恐怖岩调,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赡盘,我是刑警寧澤号枕,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站陨享,受9級特大地震影響堕澄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霉咨,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望换衬。 院中可真熱鬧捡需,春花似錦良拼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒜茴。三九已至星爪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粉私,已是汗流浹背顽腾。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抄肖。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓久信,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漓摩。 傳聞我的和親對象是個殘疾皇子裙士,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容