菜鸟学习React Native for Android 之通讯原理分析(JAVA调用JS)

主要参考自:React Native通讯原理:http://www.jianshu.com/p/17d6f6c57a5c

1.通讯框架图


2.Native调用JS

Native调用JS流程分析:

  1. MessageQueue把Native调用的方法放到JavaScriptCore中
  2. JS Module把可以调用的方法放到MessageQueue的一个对列中
  3. Native从JavaScriptCore中拿到JS的调用入口,并把Module Name、Method Name、Parameters传过去
  4. 执行JS Module的方法


个人结合源码分析理解:

CatalystInstanceImpl包含了JavaScriptModuleRegistry,后者包含了JS模块在JAVA中对应的接口,例如index.android.js中有这么一段
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
AppRegistry这个模块在JAVA中有对应的JAVA接口
package com.facebook.react.uimanager;

import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.WritableMap;

/**
 * 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);
}
CatalystInstanceImpl实例化的时候, JavaScriptModuleRegistry中就已经被放入了相关接口的class原型(点击我看看如何被存放的)

那么getJSModule是干什么的呢,其实他是生成JS在JAVA中的接口的动态代理,我们知道,动态代理是实现了接口的方法的,而在每个方法其实是调用

JavaScriptModuleInvocationHandler中的invoke方式,传入接口的方法名和参数,之所以通过动态代理,我们的目的就是把接口的方式和参数传到JS那边,另外这个动态代理

也以便于JAVA端对象。从这里我们可以看到Cataly的含义是催化剂,催化什么呢,现在看来,就是催化我们的JS中JAVA的接口转化为实例。

JAVAScriptModuleInvocationHandler有一个Cataly实例,invoke其实是调用了Cataly实例的callFunction,而callFunction里面是一个native方法

private native void callJSCallback(ExecutorToken executorToken, int callbackID, NativeArray arguments);
现在于是我们就把JS在JAVA端的接口中的方法名字和参数传递给了C++端处理了
现在再看看CatalyInstance这个,他实际上桥接了我们的C++端和JAVA端,催化了JS在JAVA端的接口产生实例(动态代理),是通信的一个关键类
现在我们通过JNI来到了libreactnativejnifb.so里面,他里面有个方法叫callJSCallback

在上面加载bundle文件的时候,会执行下面C端或者C++端的JSCExecutor的方法

(

JSCEXEcutor:我理解是JS在C端的执行者

1.负责把JS函数映射成C对象

2.通过JSCORE中的

JSObjectCallAsFunction方法,传入映射的C对象,和JAVA或OC的调用信息,以JS Function的形式执行,走到JS端
)

,把JS函数以C对象的形式存储下来,JNI实际执行的是到C实例

void JSCExecutor::bindBridge() throw(JSException) {
   auto global = Object::getGlobalObject(m_context);
   auto batchedBridgeValue = global.getProperty("__fbBatchedBridge");
   if (batchedBridgeValue.isUndefined()) {
     throwJSExecutionException("Could not get BatchedBridge, make sure your bundle is packaged   correctly");
   }

   auto batchedBridge = batchedBridgeValue.asObject();    m_callFunctionReturnFlushedQueueJS = batchedBridge.getProperty("callFunctionReturnFlushedQueue"). asObject();
   m_invokeCallbackAndReturnFlushedQueueJS = batchedBridge.getProperty(  "invokeCallbackAndReturnFlushedQueue").asObject();
   m_flushedQueueJS = batchedBridge.getProperty("flushedQueue").asObject();
}
把三个JS函数当成C对象存储下来,JNI调用到这几个C对象
JNI执行时候 通过JSCExcutor执行 jscore中的
JSObjectCallAsFunction 方法,传入一个JS映射的C对象,和相关参数,从而开始JS代码的执行
  JSValueRef result = JSObjectCallAsFunction(m_context, m_obj, thisObj, nArgs, args, &exn)

JS端被映射的相关函数如下
在JS BUNDEL生成的时会在JS全局变量里产生一个MESSAGEQUEUE,
const BatchedBridge = new MessageQueue(
() => global.__fbBatchedBridgeConfig,
serializeNativeParams
);

MESSAGEQUEUE里面有三个方法会在加载JS的时候映射为三个C++对象存下来,其中一个就是
callFunctionReturnFlushedQueue,我们通过JavaScriptCore结合这个callFunctionReturnFlushedQueue在C++中的对象调用到JS,
于是我们来到了JS端,例如(
AppRegistry只是一个例子,实际还有很多模块)在
AppRegistry.js里面,
BatchedBridge.registerCallableModule(
  'AppRegistry',
  AppRegistry
);
通过这样,把本模块注入到MessageQUUE中的一个MAP对象中,而MessageQueue中的方式
callFunctionReturnFlushedQueue中接收的参数执行callback,而找到相应的模块中的函数调用JS的APPly方式执行这个函数
  __callFunction(module: string, method: string, args: any) {
    ...
    const moduleMethods = this._callableModules[module];
    ...
    const result = moduleMethods[method].apply(moduleMethods, args);
    Systrace.endEvent();
    return result;
  }




案例:

下面这个

AppRegistry javascript module 被java 调用的例子 




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值