胡琪

为今天工作,为明天投资,为未来孵化一些东西

【React Native】js端调用安卓原生模块及2端互相通信

前面React Native编译常见问题解决和官方demo分析一文介绍了FaceBook的RN官方demo,初步介绍了官方demo的一些重要的模块及其作用。这一节就来讲解下如何在js端调用安卓原生模块,以及js端和安卓原生模块之间的互相通信的几种方式和他们的特点。因为对于任何一个跨语言的开发框架来讲,在开发过程中2端之间的相互调用和消息传递是非常基础和也是非常重要的。就像NDK开发(java和c/c++互相调用)和WebView使用一样(java和js互相调用)。

在JS端调用安卓原生模块

这里以改造官方demo为例,因为自己接触RN是因为我们的验证码SDK有个客户希望能给一个RN的demo,所以这里以在js代码中点击登陆按钮调用易盾验证码SDK为例进行讲解。期望达到的效果是:

  • 点击js代码中的登陆按钮,显示验证码界面(js端调用安卓原生模块)
  • 滑动验证码验证通过,js端弹出一个“验证成功”提示框,反之弹出“验证失败”提示框(安卓端与js端通信)

这个demo能够很好的把js端调用安卓原生模块(验证码SDK)和安卓端向js端传递消息(告知验证是否通过)包含进来。打个广告,欢迎大家使用网易易盾验证码SDK服务进行行为式验证,告别繁琐的输入字符验证:http://dun.163.com/trial/jigsaw

首先修改demo的App.js。添加一个按钮以及监听事件。

在登陆按钮的事件响应函数中调用安卓端的SDK,所以接下来就是在安卓端创建要被js调用的原生模块。

在安卓端创建要被js调用的原生模块

  1. 创建一个原生模块类继承自ReactContextBaseJavaModule抽象类,实现getName方法,返回该原生模块的模块名。(该方法的返回值即为需要在JS代码中引入的模块名
  2. 在需要被JS代码调用的方法处加上@ReactMethod注解

  1. 创建一个包层次的模块管理类实现ReactPackage接口,实现该接口的2个方法。在createNativeModules方法中将前面创建的模块类添加到包模块管理List中

  1. 在demo的MainApplication的相应位置将前面创建的包管理模块添加进去

之间的层次关系可以这么理解:

  • 继承自ReactContextBaseJavaModule的原生模块相当于java端的需要被js端调用的类模块,在这个模块中返回该模块希望被js端调用的类模块名(实现getName方法)和希望被js端调用的函数(在函数上面加上@ReactMethod注解)
  • 实现了ReactPackage的原生模块相当于java端的包层次模块,在这个模块中添加前面创建的类模块
  • 在MainApplication内部类ReactNativeHost的getPackages方法中添加前面创建的包管理模块

js端调用安卓端创建的类模块

  1. 引入原生模块NativeModules

  1. 调用安卓端相应模块的RN方法

2端之间的相互通信

2端之间的消息传递方式可以概括为以上3种方式,我们一个一个来看。

回调Callback

  • 在安卓端需要被JS调用的ReactMethod中增加Callback这个对象参数,在需要发送消息的地方使用Callback的invoke方法传递消息。该函数定义如下:

也就是该方法的参数是一个对象数组。因此如果我们有多个消息要传递,直接把多个消息对象作为参数传入调用即可。

  • 在需要发送消息的地方调用invoke方法

  • 在JS端调用时传入回调函数接收回调消息.

回调函数方式,JS端是主动调用方,安卓端是被动消息发送方。对于验证码验证而言,安卓端可能会多次触发验证结果,即多次调用invoke方法。但是因为JS端只调用了一次原生模块函数。所以只会回调一次。因此对于验证码而言,不大合适使用回调方式从安卓端向js端传递消息。

发送事件

在JS端建立事件监听函数,在安卓端调用RN提供的事件发送API发送事件。

安卓端代码

js端代码

事件发送方式安卓端是主动方,js端是被动监听方,所以可以进行多次消息传递。而且这种方式无需作为RN函数的参数,所以代码耦合性低。

Promises

将安卓原生模块声明的RN方法的最后一个参数定义为Promise对象,则在JS端调用该RN方法时会返回一个Promise对象。在JS端调用该方法的时候一般会配合ES7标准的async/await语法。安卓端在需要发送消息的地方使用Promise的resolve方法传递消息。关于Promise的介绍可以参看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

安卓端代码
在RN方法的最后一个参数处添加Promise参数

在需要发送消息的地方使用Promise的resolve方法传递消息

js端代码
调用RN函数,该函数会返回一个Promise对象,从该对象中得到安卓端发送过来的消息

最终demo效果及源码

 

 

 

 

打赏

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注