博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RN与原生交互(二)——数据传递
阅读量:6656 次
发布时间:2019-06-25

本文共 5647 字,大约阅读时间需要 18 分钟。

我的上篇文章中简单介绍了RN与原生基本的页面跳转,本篇主要总结RN和原生之间的数据传递方式,讲解RN和原生端之间如何互相传递数据。

Demo地址:

RN向原生传递数据

在上一篇文章中已经说明了怎样分别在iOS和Android端创建module类,怎样使用。这里不再赘述。RN向原生传递数据需要我们在module类中定义相关方法,方法参数即为RN传递过来的数据,原生端根据参数做相应处理。

传递字符串

iOS代码如下:

/// RN向原生传递字符串RCT_EXPORT_METHOD(getStringFromReactNative:(NSString *)s) {  NSString *msg = [NSString stringWithFormat:@"RN传递过来的字符串:%@", s];  [self showAlert:msg];}复制代码

Android如下:

/**     * RN向原生传递字符串     * @param s     */    @ReactMethod    public void getStringFromReactNative(String s) {        Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();    }复制代码

传递整数或其它数字类型与此类似。

传递字典

这个很关键,iOS端接收数据类型还是NSDictionary类型,但Android端接收参数可不是Map、HashMap之类的,而是ReadableMap,这里要划重点。

/**     * RN向原生传递字典。这里原生端接收RN传过来的字典类型是ReadableMap     * @param map     */    @ReactMethod    public void getDictionaryFromRN(ReadableMap map) {        System.out.print(map);        Toast.makeText(mContext, "已收到字典数据", Toast.LENGTH_SHORT).show();    }复制代码

iOS端核心代码:

/// RN向原生传递字典RCT_EXPORT_METHOD(getDictionaryFromRN:(NSDictionary *)dict) {  NSLog(@"RN传递过来的字典:%@", dict);  NSString *name = [dict objectForKey:@"title"];  [self showAlert:name];}复制代码

传递数组

iOS端接收参数类型可定义为NSArray,但Android端接收参数需要定义为ReadableArray,不能是java中的集合类型,如List、ArrayList是解析不到数据的。

Android代码:

@ReactMethod    public void getArrayFromRN(ReadableArray array) {        System.out.print(array);        Toast.makeText(mContext, "已收到数组数据", Toast.LENGTH_SHORT).show();    }复制代码

原生向RN回调数据

以Android端为例,RN在调用以下方法时可以通过回调获取到原生端返回的数据。

/**     * 原生通过回调的形式向RN端传递string     * @param callback     */    @ReactMethod    public void passStringBackToRN(Callback callback) {        callback.invoke("This is a string from Native");    }    /**     * 原生通过回调的形式向RN端传递字典。这里传出去的字典类型必须是WritableMap,java中的Map、HashMap是不能传递到RN的     * @param callback     */    @ReactMethod    public void passDictionaryBackToRN(Callback callback) {        WritableMap map = Arguments.createMap();        map.putString("name", "小明");        map.putInt("age", 20);        map.putString("gender", "male");        map.putBoolean("isGraduated", true);        callback.invoke(map);    }    /**     * 原生通过回调的形式向RN端传递数组。这里传出去的字典类型必须是WritableArray     * @param callback     */    @ReactMethod    public void passArrayBackToRN(Callback callback) {        WritableArray array = Arguments.createArray();        array.pushString("React Native");        array.pushString("Android");        array.pushString("iOS");        callback.invoke(array);    }    @ReactMethod    public void passPromiseBackToRN(String msg, Promise promise) {        if (!msg.equals("")) {            promise.resolve(true);        } else {            promise.reject("warning", "msg cannot be empty!");        }    }复制代码

iOS端在回调数据时一般使用RCTResponseSenderBlock,任何数据类型都以block形式返回,示例如下:

/// 回传数组到RN端RCT_EXPORT_METHOD(passArrayBackToRN:(RCTResponseSenderBlock)block) {  if (block) {    NSArray *items = @[@"React Native", @"Android", @"iOS"];    block(@[items]);  }}复制代码

iOS端以promise形式返回数据与Android不同,Android端定义了一个Promise类,iOS端还是通过block形式给出回调,使用RCTPromiseResolveBlock和RCTPromiseRejectBlock

/// 以promise形式回传数据到RN端RCT_EXPORT_METHOD(passPromiseBackToRN:(NSString *)msg resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {  if (![msg isEqualToString:@""]) {    resolve(@(YES));  } else {    reject(@"warning", @"msg cannot be empty!", nil);  }}复制代码

发送事件

Android端核心代码:

public void sendEvent(String eventName) {        String dataToRN = "这是发给RN的字符串";        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, dataToRN);    }复制代码

sendEvent方法定义在module类中,在需要发送事件的地方调用sendEvent方法就可以将事件通知发给RN端。

RN端监听Android端发来的通知如下,这里假设事件名称为“CustomEventName”

componentWillMount(){        DeviceEventEmitter.addListener('CustomEventName', (e)=> {             console.log("接收到通知") ;       });     }  复制代码

iOS端与Android不同,不使用DeviceEventEmitter做监听,而是用NativeEventEmitter。具体实现方案如下:

  1. 使Module类继承RCTEventEmitter,重写supportedEvents方法,在这个方法中声明支持的事件名称。
  2. 在Module类的init方法中使用NSNotificationCenter监听iOS端要发送事件的操作。
  3. 在NSNotification对应的通知方法中将事件发送给RN。

核心代码:

+ (id)allocWithZone:(struct _NSZone *)zone {  static DataTransferModule *sharedInstance = nil;  static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{    sharedInstance = [super allocWithZone:zone];  });  return sharedInstance;}- (instancetype)init {  self = [super init];  if (self) {    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];    [defaultCenter removeObserver:self];    [defaultCenter addObserver:self                      selector:@selector(sendCustomEvent:)                          name:@"sendCustomEventNotification"                        object:nil];  }  return self;}/// 接收通知的方法,接收到通知后发送事件到RN端。RN端接收到事件后可以进行相应的逻辑处理或界面跳转- (void)sendCustomEvent:(NSNotification *)notification {  [self sendEventWithName:@"CustomEventName" body:@"这是发给RN的字符串"];}/// 重写方法,定义支持的事件集合- (NSArray
*)supportedEvents { return @["CustomEventName"];}复制代码

比如在iOS端我有个页面A,点击页面中的一个button需要关掉当前页面并且发送数据给RN端,使RN端接收到数据后做跳转操作。那么在A中button的点击方法如下:

- (void)buttonClicked:(id)sender {  [[NSNotificationCenter defaultCenter] postNotificationName:@"sendCustomEventNotification" object:nil];  [self dismissViewControllerAnimated:YES completion:nil];}复制代码

Module类中接收到通知后就将这个要做的操作发送给RN了。RN端监听方法如下:

const DataTransferModule = NativeModules.DataTransferModule;componentDidMount() {    let eventEmitter = new NativeEventEmitter(DataTransferModule);      this.listener = eventEmitter.addListener("CustomEventName", (result) => {        this.showAlert("获取到事件通知" + result);      })  }    componentWillUnmount() {    this.listener && this.listener.remove();  }复制代码

转载于:https://juejin.im/post/5b20ceb16fb9a01e4f47cd49

你可能感兴趣的文章
发送邮件(E-mail)方法整理合集
查看>>
(转)sqlite developer注册方法
查看>>
最大值 最小值 最初值 最末值
查看>>
Anagrams
查看>>
iphone手机分辨率--持久维护
查看>>
DRP——Servlet(一)
查看>>
pydoc介绍
查看>>
使用rsyslog+loganalzey收集日志显示客户端ip
查看>>
EF实现主从表自动生成主键保存
查看>>
Atitit.程序包装exe启动器 打包 发布 设计 -生成exe java
查看>>
Mac下MySQL卸载方法 转载
查看>>
Chrome for Android在Chromium代码库中的提交patch
查看>>
iphone 拨打电话的 两种方法-备
查看>>
python小程序:备份文件
查看>>
为什么HikariCP被号称为性能最好的Java数据库连接池,怎样配置使用
查看>>
高德地图API INVALID_USER_SCODE问题以及keystore问题
查看>>
C# WinForm 添加Windows Media Player 控件调试出现未能加载文件或程序集Interop.WMPLib,该怎么解决...
查看>>
C# 抓取网页Html源码 (网络爬虫)
查看>>
盖得化工4——多线程+余数
查看>>
iOS开发小技巧--适当的清空模型中的某个数据,达到自己的需求,记得最后将数据还原(百思项目评论页面处理最热评论)...
查看>>