• 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 > React-Native系列Android——Native与Javascript通信原理(二)

React-Native系列Android——Native与Javascript通信原理(二)

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

网友通过本文主要向大家介绍了javascript运行原理,javascript的执行原理,javascript 闭包原理,javascript原理,javascript工作原理等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

React-Native系列Android——Native与Javascript通信原理(二)


前一篇博客分析了Native端向Javascript端通信的全流程,这次来研究下Javascript端向Native端通信的全流程,与前篇恰好构成一个基本完整的通信机制。

本篇博客内容与前篇联系较大,有些分析过的东西这次就直接拿来用了,不再赘述,所以希望阅读这篇文章之前先熟悉下前篇:
React-Native系列Android——Native与Javascript通信原理(一)
 

引用下前篇中的通信模型:
\

Native与Javascript之间的双向通信其实是你来我往的一个循环过程,就好像是两个人在对话,你一句我一句然后你再一句我再一句。那么总有一个会话的发起者吧?当然是Native了,因为所有的行为都是从Native端发起的,用户操作直接面向的也是Native。所以这个通信模型又可以看成是Native发起会话,然后Javascript进行应答。

所以,今天的博文重点就是分析Javascript是如何应答Native,同时Native又是如何处理来自Javascript的应答的。


1、Javascript的应答

还记得前篇Bridge层章节中JSCExecutor::callFunction最后有一个callNativeModules的调用吗?忘记了不要紧,再来回顾下jni/react/JSCExecutor.cpp中的这段代码吧!

void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) {
  // TODO:  Make this a first class function instead of evaling. #9317773
  std::vector call{
    moduleId,
    methodId,
    std::move(arguments),
  };
  std::string calls = executeJSCallWithJSC(m_context, "callFunctionReturnFlushedQueue", std::move(call));
  m_bridge->callNativeModules(*this, calls, true);
}
static std::string executeJSCallWithJSC(
    JSGlobalContextRef ctx,
    const std::string& methodName,
    const std::vector& arguments) {

  ...

  // Evaluate script with JSC
  folly::dynamic jsonArgs(arguments.begin(), arguments.end());
  auto js = folly::to(
      "__fbBatchedBridge.", methodName, ".apply(null, ",
      folly::toJson(jsonArgs), ")");
  auto result = evaluateScript(ctx, String(js.c_str()), nullptr);
  return Value(ctx, result).toJSONString();
}

executeJSCallWithJSC方法执行Javascript最终脚本后返回了一个名为calls的JSON串,这个字符串又被塞进了Bridge.cpp的callNativeModules方法,这个方法大家都能根据字面意思猜测到是调用Native端组件的,那么这个JSON串内容就是来自Javascript的应答内容了。

callNativeModules方法及里面的细节我们暂时放一放,先来看看这个Javascript的应答内容里面到底是些神马东西!

前篇里面,被WebKit库执行的Javascript语句,大家应该还记得吧,最终如下:

MessageQueue.callFunctionReturnFlushedQueue.apply(null, module, method, args);

再次看一下MessageQueue.js的callFunctionReturnFlushedQueue方法内容:

callFunctionReturnFlushedQueue(module, method, args) {
    guard(() => {
      this.__callFunction(module, method, args);
      this.__callImmediates();
    });

    return this.flushedQueue();
  }
  flushedQueue() {
    this.__callImmediates();

    let queue = this._queue;
    this._queue = [[], [], [], this._callID];
    return queue[0].length ? queue : null;
  }

返回的是flushedQueue()方法,而flushedQueue()返回的是this._queue数组或者null。

这里有个小细节,flushedQueue()并不是直接返回this._queue的,而是新定义了一个局部变量queue,先将this._queue的值赋给queue用于返回,然后又清空数组内容。这种处理方式,说明了this._queue数组是专门存放应答Native端内容的,每次应答之后都会置空然后等待下一次的会话到来。

那么,问题来了!应答Native端的内容是如何被放进this._queue数组里面的呢?

有点抽象,也有点玄乎了,我们不妨结合一下场景分析:假设用户点击了文本,然后手机弹出一个Toast,这个Toast其实就是来自Javascript的应答,如果用React-Native代码写出来应该是这样:

var ToastAndroid = require('ToastAndroid')
ToastAndroid.show('Awesome, Clicking!', ToastAndroid.SHORT);

当然,弹这个Toast效果是需要Native端来做了,但是‘Awesome, Clicking!’文案和SHORT,两个参数是来自Javascript端的,Javascript端会告诉Native端弹一个内容‘Awesome, Clicking!’时长SHORT的Toast,其实就是对用户点击这个会话的应答了。

那我么就以ToastAndroid为例,来分析下Javascript的应答,也就是如何把Awesome, Clicking!’和SHORT两个参数塞进this._queue数组的。

先来研究一下ToastAndroid的代码,位于\node_modules\react-native\Libraries\Components\ToastAndroid\ToastAndroid.android.js

'use strict';

var RCTToastAndroid = require('NativeModules').ToastAndroid;

var ToastAndroid = {

  SHORT: RCTToastAndroid.SHORT,
  LONG: RCTToastAndroid.LONG,

  show: function (
    message: string,
    duration: number
  ): void {
    RCTToastAndroid.show(message, duration);
  },

};

module.exports = ToastAndroid;

里面使用的是RCTToastAndroid,而RCTToastAndroid又是NativeModules里的一个属性。所以,这一段Toast的调用代码等价于:

NativeModules.RCTToastAndroid.show(message, duration);

下面来看看NativeModules吧,代码位于\node_modules\react-native\Libraries\BatchedBridge\BatchedBridgedModules\NativeModules.js

const BatchedBridge = require('BatchedBridge');
const RemoteModules = BatchedBridge.RemoteModules;
...
const NativeModules = {};
...
module.exports = NativeModules;

乍一看,NativeModules对象里面是空的,并没有所谓的RCTToastAndroid属性,但是不要忘了,Javascript是可以通过Object.defineProperty方式定义对象属性的,也算是其独门绝技了,仔细阅读一下NativeModules的代码,果然找到了一些蛛丝马迹,我们来看看:

const NativeModules = {};
Object.keys(RemoteModules).forEach((moduleName) => {
  Object.defineProperty(NativeModules, moduleName, {
    enumerable: true,
    get: () => {
      let module = RemoteModules[moduleName];
      if (module && typeof module.moduleID === 'number' && global.nativeRequireModuleConfig) {
        const json = global.nativeRequireModuleConfig(moduleName);
        const config = json && JSON.parse(json);
        module = config && BatchedBridge.processModuleConfig(config, module.moduleID);
        RemoteModules[moduleName] = module;
      }
      return module;
    },
  });
});

这段代

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

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

  • React-Native系列Android——Native与Javascript通信原理(二)

相关文章

  • 2017-05-26android关于线程的那些事,android那些事
  • 2017-05-26Android项目:手机安全卫士(16)—— 复杂 ListView浅析
  • 2017-05-26手机产品设计之用户引导,手机产品设计引导
  • 2017-05-26硅谷社交6--添加联系人--发送添加好友邀请,硅谷6--
  • 2017-05-26git版本控制工具(二)----本地版本库的常用操作,git----
  • 2017-05-26Android Studio第一次提交git使用,androidgit
  • 2017-05-26ConfigParser写配置文件乱序问题
  • 2017-05-26Apache Cordova开发Android应用程序——番外篇,cordovaandroid
  • 2017-05-26HTTP 首部字段详细介绍,首部字段详细介绍
  • 2017-05-26整理分享原生态mac AndroidStudio的快捷键,studio快速整理代码

文章分类

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

最近更新的内容

    • android 打造炫酷导航栏(仿UC头条)
    • 用Kotlin创建第一个Android项目(KAD 01),kotlinandroid
    • android 在5.0以后不允许使用隐式Intent方式来启动Service,androidintent
    • 日志文件之出错处理
    • 模仿轻仿蘑菇街应用源码,仿蘑菇街源码
    • Glide生命周期管理
    • Android Studio 优秀插件(二): Parcelable Code Generator,androidparcelable
    • Android框架设计模式(四)——Adapter Method
    • 如何取得nginx做反向代理时的真实IP?
    • 4.1.3 Activity登堂入室

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

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