• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制,buglyreactnative

【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制,buglyreactnative

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制,buglyreactnative等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制,buglyreactnative


Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处。

本文从源码角度剖析 RNA 中 Java <> Js 的通信机制(基于最新的 RNA Release 20)。

对于传统 Java<>Js 通信而言,Js 调用 Java 通不外乎 Jsbridge、onprompt、log 及 addjavascriptinterface 四种方式,在 Java 调用 Js 只有 loadurl 及高版本才支持的 evaluateJavaScript 两种。但在 RN 中没有采用了传统 Java 与 Js 之间的通信机制,而是借助 MessageQueue 及模块配置表,将调用转化为{moduleID, methodID,callbackID,args},处理端在模块配置表里查找注册的模块与方法并调用。

一、Module Registry

在 RNA 中,在应用启动时根据 ReactPackage 会自动生成 NativeModuleRegistry 及 JavaScriptModuleRegistry 两份模块配置表,包含系统及自定义模块,Java 端与 Js 端持有相同的模块配置表,标识为可识别为 Native 模块或 Js 模块都是通过实现相应接口,并将实例添加 ReactPackage 的 CreactXXModules 方法即可。

CoreModulesPackage.java

@Override
public List<NativeModule> createNativeModules(
   ReactApplicationContext catalystApplicationContext) {
 return Arrays.<NativeModule>asList(
   new AndroidInfoModule(),
   new DeviceEventManagerModule(catalystApplicationContext, mHardwareBackBtnHandler),
   new DebugComponentOwnershipModule(catalystApplicationContext));
}

@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Arrays.asList(
  DeviceEventManagerModule.RCTDeviceEventEmitter.class,
  JSTimersExecution.class,
  RCTEventEmitter.class,
  RCTNativeAppEventEmitter.class,
  AppRegistry.class
}

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return new ArrayList<>(0);
}

Js 模块 extends 自 JavascriptModule,映射在 Js 相对应 Js 模块,通过动态代理实现调用 Js 模块。下例 AppRegistry.java 为在加载完 Jsbundle 后,Native 去启动 React Application 的总入口,appkey 为应用的 ID。映射每个 JavascriptModule 的信息保存在 JavaScriptModuleRegistration 中,统一由 JavaScriptModuleRegistry 统一管理。

AppRegistry.java

public interface AppRegistry extends JavaScriptModule {

  void runApplication(String appKey, WritableMap appParameters);
  void unmountApplicationComponentAtRootTag(int rootNodeTag);

}

Java 模块 extends 自 BaseJavaModule,在 Js 层存在同名文件识别为可调用的 Native。重写 getName 识别为 Js 的模块名,重写 getConstants 识别为 Js 可访问的常量,方法通过注解 @ReactMethod 可识别供 Js 调用的 API 接口,所有 Java 层提供的模块接口统一由 NativeModuleRegistry 统一暴露。

AndroidInfoModule.java

public class AndroidInfoModule extends BaseJavaModule {

 @Override
 public String getName() {
  return "AndroidConstants";
 }

 @Override
 public @Nullable Map<String, Object> getConstants() {
   HashMap<String, Object> constants = new HashMap<String, Object>();
   constants.put("Version", Build.VERSION.SDK_INT);
   return constants;
  }
}

二、Java -> Js

完整通信机制流程图:

bugly 干货分享

简要说明下这5个步骤:

1.CatalystanceImpl 为 Js<>Java 通信高层封装实现类,业务模块通过 ReactInstanceManager 与 CatalystanceImpl 间接通信,调用Js暴露出来的API。

2.将来自Java层的调用拆分为 ModuleID,MethodID 及 Params,JavaScriptModuleInvocationHandler 通过动态代理方式交由 CatalystanceImpl 统一处理。

整体调用关系比较清晰,下面分别借助源码说明上面整个流程。

在 Java 层 implements JavaScriptModule 这个 interface 被识别为 Js 层暴露的公共 Module,(由JS不允许的方法名称重载,所以继承自 JavaScriptModule 同样不允许方法重载)。JavaScriptModuleRegistry 负责管理所有的 JavaScriptModule,持有对 JavaScriptModuleInvocationHandler 的引用,通过 invoke 的方式,统一调度从 Java -> Js 的调用。

JavaScriptModuleInvocationHandler.java

private static class JavaScriptModuleInvocationHandler implements InvocationHandler {

  private final CatalystInstanceImpl mCatalystInstance;
  private final JavaScriptModuleRegistration mModuleRegistration;

  public JavaScriptModuleInvocationHandler(
      CatalystInstanceImpl catalystInstance,
      JavaScriptModuleRegistration moduleRegistration) {
    mCatalystInstance = catalystInstance;
    mModuleRegistration = moduleRegistration;
  }

  @Override
  public @Nullable Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    String tracingName = mModuleRegistration.getTracingName(method);
mCatalystInstance.callFunction(
       mModuleRegistration.getModuleId(),
       mModuleRegistration.getMethodId(method),
       Arguments.fromJavaArgs(args),
    tracingName);
return null;
 }
}

CatalystInstance 为 Java 与 Js 之前通信的高层接口,已被抽离成接口,CatalystInstanceImpl 为其基础实现类,业务侧在 ReactInstanceManager Create ReactContext 时通过 Builder 构建实例化,业务一般不直接持有 CatalystInstance 的引用,一般通过 Framework 层的 ReactInstanceManager 的实现类进行访问。持有对 JavaScriptModuleRegistry& RativeModuleRegistry 的引用。

CatalystInstanceImpl.java

@Override
public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
return Assertions.assertNotNull(mJSModuleRegistry).getJavaScriptModule(jsInterface);
}

在 CatalystInstance 初始化时会调用 initializeBridge 初始化私有成员 ReactBridge,ReactBridge 做为 JNI 层的通信桥接对象,负责 Java<>JCS 之间的通信。在 Java 层调用 JS 会调用 JNI 的 CallFunction 的方法,通过 JSC 转接到 JS 层的模块。

CatalystInstanceImpl.java

private ReactBridge initializeBridge(
    JavaScriptExecutor jsExecutor,
    JavaScriptModulesConfig jsModulesConfig) {
  mReactQueueConfiguration.getJSQueueThread().assertIsOnThread();
  Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");

  Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactBridgeCtor");
  ReactBridge bridge;
  try {
    bridge = new ReactBridge(
       jsExecutor,
       new NativeModulesReactCallback(),
       mReactQueueConfiguration.getNativeModulesQueueThread());
} finally {
  Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}

 Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "setBatchedBridgeConfig");
 try {
   bridge.setGlobalVariable(
       "__fbBatchedBridgeConfig",
       buildModulesConfigJSONProperty(mJavaRegistry, jsModulesConfig));
   bridge.setGlobalVariable(
       "__RCTProfileIsProfiling",
       Systrace.isTracing(Systrace.TRACE_TAG_REACT_APPS) ? "true" : "false");
 } finally {
   Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
 }

 return bridge;
}
ReactBridge.java

/**
* All native functions are not thread safe and appropriate queues should be used
 */
public native void loadScriptFromAssets(AssetManager assetManager, String assetName);
public native void loadScriptFromFile(@Nullable String fileName, @Nullable String sourceURL);
public native void callFunction(int moduleId, int methodId, NativeArray arguments);
public native void invokeCallback(int callbackID, NativeArray arguments);
public native void setGlobalVariable(String propertyName, String jsonEncodedArgument);
public native boolean supportsProfiling();
public native void startProfiler(String title);
public native void stopProfiler(String title, String filename);
private native void handleMemoryPressureModerate();
private native void handleMemoryPressureCritical();

Onload.cpp 为 C++ 层主要入口,涵盖类型操作,jsbundle 加载及全局变量操作等。通过 bridge.cpp 的转接到 JSExector.cpp 执行 JS。JSExector.cpp 最终将调用转发到 JSCHelper.cpp 中执行evaluateScript 的函数,从而执行 JS 的调用。

OnLoad



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制,buglyreactnative

相关文章

  • 2017-05-26andriod 获得drawable下所有图片,
  • 2017-05-26Android6.0系统增加那些新特性
  • 2017-05-26【1】Android 学习笔记 【第一个安卓程序】,android安卓
  • 2017-05-26可展开的列表组件——ExpandableListView深入解析,expandablelist展开
  • 2017-05-26机顶盒上gridview+ScrollView的使用。,gridviewscrollview
  • 2017-05-26使用phonegap播放音频,phonegap播放音频
  • 2017-05-26Android Studio下运行开源项目9GAG遇到的问题
  • 2017-05-26Android DEX 基础,androiddex基础
  • 2017-05-26Android工程文件下assets文件夹与res文件夹的区别
  • 2017-05-26好玩的Handler,好玩Handler

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • androidStudio通过svn进行版本控制,androidstudiosvn
    • android开发时间和日期的代码实现工具类(一),android工具类
    • Android开发学习—— Broadcast广播接收者,androidbroadcast
    • Android保持屏幕常亮,android屏幕常亮
    • Android sdk content loader 0%,androidsdk
    • Activity与Service进行数据交互,activityservice
    • Android开发学习——android反编译,开发android反编译
    • 8.3.10 Paint API之—— ColorFilter(颜色过滤器)(2-3)
    • ImageView的ScaleType属性,imageviewscaletype
    • 【Android】如何写一个JsBridge

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有