前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React-Native与原生模块间的几种通信方式

React-Native与原生模块间的几种通信方式

原创
作者头像
conanma
发布2022-01-08 13:59:25
2.3K0
发布2022-01-08 13:59:25
举报
文章被收录于专栏:正则正则

每种语言都有自己的设计理念、语法、运行环境,这也导致了不同语言间相互交流通信时必须要有中介来翻译,如JAVA与C/C++通过JNI来交流、OC与C/C++需要在.mm文件混编、而JAVA/OC与Lua通信时需要通过C/C++语言来做中介。那么在React-Native中JSX是如何与底层模块进行通信的呢?这里主要以iOS系统来做说明。

原理

通信本质上是信息的交流,具体到计算机语言则是数据的流动。应用中数据在React-Native与原生模块间的流动与共享,完成了与用户的交互,达成了应用的目标。React-Native与OC间通信的数据只能是下面的几种类型(前为JS类型,后为OC类型):

  • string-NSString
  • number - int/NSInteger/float/double/NSNumber
  • boolean - BOOL/NSNumber
  • array - NSArray
  • object - NSDictionary(NSString型key, value可以为这里的其它类型)
  • func - RCTResponseSenderBlock

其它类型的数据需要通过一定的规则转换成这几种类型后(一般都会转换成JSON串)再通信.

React-Native本质是通过JavaScriptCore.framework实现JS代码与OC代码间的互动。因此下面说的几种方式在本质原理上都是相同的,不同的地方只是在于实现形式与方法的差别。

函数调用

在将原生模块封装并提供给React-Native使用时,可以通过RCT_EXPORT_METHOD()宏向React-Native侧定义其可以调用的接口函数,完成两模块间的通信。

代码语言:javascript
复制
//定义了startVPN接口,React-Native将VPN的具体参数通过该接口传入到原生模块,开启指定的VPN
RCT_EXPORT_METHOD(startVPN:(NSDictionary*)config)
{
  LSShadowSocksDataMode* mode = [[LSShadowSocksDataMode alloc] initWithDictionary:config];
  [self.manager startVPN:mode];
}

除了传入数据外,通过可以通过这种方式从原生侧获取数据。最容易想到的是通过返回值获取,可惜的是RCT_EXPORT_METHOD宏不支持返回值,不过其提供了另外一种实现返回值的方式:

代码语言:javascript
复制
RCT_EXPORT_METHOD(isOpen:(RCTResponseSenderBlock)callback)
{
  BOOL open = [self.manager status];
  callback(@[[NSNull null], @[@(open)]]);
}

通过回调函数的形式实现返回值的效果,达到了数据交换的目的。

属性共享

这种方式主要针对于UI控件来说的。React-Native中最基础的UI类型是RCTRootView,该类有一个初始化方法initWithBridge:moduleName:initialProperties:,第三个参数initialProperties表示的是UI控件的初始属性值,类型为NSDictionary,其最终会被同步到由第二个参数定义的React-Native类的props中,即完成了两个模块间的数据交流。

代码语言:javascript
复制
NSArray *imageList = @[@"http://foo.com/bar1.png",
                  @"http://foo.com/bar2.png"];

NSDictionary *props = @{@"images" : imageList};

RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                      moduleName:@"ImageBrowserApp"
                                     initialProperties:props];
代码语言:javascript
复制
import React, { Component } from 'react';
import {
  AppRegistry,
  View,
  Image,
} from 'react-native';

class ImageBrowserApp extends Component {
  renderImage(imgURI) {
    return (
      <Image source={{uri: imgURI}} />
    );
  }
  render() {
    return (
      <View>
        {this.props.images.map(this.renderImage)}
      </View>
    );
  }
}

AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);

初始化接口只能在UI组件建立时使用,如果需要在UI组件的生命周期内通信呢,RCTRootView提供了appProperties这样一种机制:

代码语言:javascript
复制
NSArray *imageList = @[@"http://foo.com/bar3.png",
                   @"http://foo.com/bar4.png"];
rootView.appProperties = @{@"images" : imageList};

通知

OC中使用NSNotificationCenter向整个应用发送通知,所有对该通知感兴趣的对象都会获得该通知并执行相应的动作。React-Native中也提供有类似的机制:RCTEventEmitter。原生模块继承该类后,就可以向React-Native侧发送通知,而React-Native就能够接收到该通知,并处理一并传送过来的数据了。

代码语言:javascript
复制
-(void)vpnStatusChanged:(NSNotification*)notification
{
  NEVPNStatus status = [self.manager status];
  NSString* value = nil;
  switch (status) {
    case NEVPNStatusReasserting:
      value = @"重新连接中";
      break;
    case NEVPNStatusConnecting:
      value = @"连接中";
      break;
    case NEVPNStatusConnected:
      value = @"已连接";
      break;
    case NEVPNStatusDisconnecting:
      value = @"断开连接中";
      break;
    case NEVPNStatusDisconnected:
    case NEVPNStatusInvalid:
      value = @"末连接";
      break;
    default:
      break;
          }
  if(value){
    [self sendEventWithName:@"VpnStatus" body:@{@"status":value}];
  }
}

这里将V**的状态通过通知发送到React-Native侧,由React-Native将V**的状态显示的UI界面上。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理
  • 函数调用
  • 属性共享
  • 通知
相关产品与服务
VPN 连接
VPN 连接(VPN Connections)是一种基于网络隧道技术,实现本地数据中心与腾讯云上资源连通的传输服务,它能帮您在 Internet 上快速构建一条安全、可靠的加密通道。VPN 连接具有配置简单,云端配置实时生效、可靠性高等特点,其网关可用性达到 99.95%,保证稳定、持续的业务连接,帮您轻松实现异地容灾、混合云部署等复杂业务场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档