ReactNative进阶(五):React Native与原生通信

文章目录

    • 一 、前言
    • 二、RN与安卓通信
      • 2.1 RN 调用安卓原生组件
      • 2.2 RN 应用消息机制方式与安卓原生代码切换
      • 2.3 RN 应用 Promise 机制与安卓原生代码通信
      • 2.4 RN 应用 callback 回调方式与安卓原生代码通信
    • 三、RN与IOS通信
      • 3.1 定义导出的方法名
      • 3.2 promise 实现回调函数
      • 3.3 继承 RCTEventEmitter 类
    • 四、拓展阅读

一 、前言

RN项目开发阶段,需要实现RN与原生应用间进行数据通讯。

二、RN与安卓通信

2.1 RN 调用安卓原生组件

  1. 用Android Studio打开一个已经创建好的RN项目,选择android/build.gradle文件。
  2. 创建一个类MyNativeModule继承ReactContextBaseJavaModule,暴露出一些让RN调用的方法,封装成一个原生模块。
public class MyNativeModule extends ReactContextBaseJavaModule{
}

实现getName方法,用于返回RN代码需要寻找的类的名称。

//RN代码要通过名字来调用该类的方法
@Override
public String getName() {return "ToastModule";
}

实现类的构造方法,将传入的上下文赋值给类内部私有的上下文。

// 创建一个上下文,放到构造函数中,得到reactContext
private ReactApplicationContext mContext;
public MyNativeModule(ReactApplicationContext reactContext){super(reactContext);mContext = reactContext;
}

创建暴露给RN调用的方法,需要用注释符号@ReactMethod修饰。

//方法不能返回值。因为被调用的原生代码是异步的。原生代码执行结束之后只能通过回调函数或者发送消息给RN。
@ReactMethod
public void rnCallNative(String msg){//这个方法是说弹出一个弹窗到界面Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();
}
  1. 在原生代码中创建一个类实现接口ReactPackage包管理器,并且把第二步已经创建好的类加入到原生模块列表里。
public class MyReactPackage implements ReactPackage {@Overridepublic List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {List<NativeModule> modules = new ArrayList<>();modules.add(new MyNativeModule(reactContext));return modules;}@Overridepublic List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {return Collections.emptyList();}
}
  1. 将创建好的包管理器添加到ReactPackage列表里,也就是MainApplication代码中,在类里找到方法getPackages方法,将包管理器添加进去。
@Override
protected List<ReactPackage> getPackages() {return Arrays.<ReactPackage>asList(new MainReactPackage(),new MyReactPackage());
}
  1. 在RN代码中用NativeModules组件去调用原生模块。
    导入组件
import {AppRegistry,StyleSheet,Text,View,NativeModules,
} from 'react-native';

设置方法调用原生代码

call_button(){NativeModules.ToastModule.rnCallNative('RN与安卓开发');
}

布置UI 在render方法里面设置当用户点击文字时,调用自定义的方法call_button。并且以这种形式创建的方法需要进行绑定。

render() {return(<View style={styles.container}><Text  onPress={this.call_button.bind(this)}>测试原生通讯</Text></View>);
}
....
const styles = StyleSheet.create({container: {flex:1,backgroundColor:'deeppink',flexDirection:'row',justifyContent:'center',alignItems:'center'    },
});

RN调用原生的方法,此时安卓的application就会启动,完成之后它会去找Package列表,进而找到自己创建的列表。而在组件的列表里面有一个原生模块列表,到自己的模块列表里面调用模块里的方法就完成了调用。

2.2 RN 应用消息机制方式与安卓原生代码切换

在原生代码中添加一个按钮,当用户从RN界面调用原生代码就会进入到原生代码开发的界面中,而点击原生代码中的按钮就会返回到RN界面。

实施步骤如下:

  1. 在与MainApplication同级的目录下创建一个MyActivity,会自动生成一个自动布局文件activity_my做布局的工作。
  2. 打开布局文件,将左下角的Design切换成Text文件,为原生界面创建一个按钮并且布局。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutandroid:layout_width = "match_parent"android:layout_height="match_parent"xmlns:android = "http://schemas.android.com/apk/res/android"><Buttonandroid:text="goBack"android:onClick="onBack"android:layout_centerInParent="true"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
</RelativeLayout>
  1. 回到新创建的MyActivity代码,实现onBack方法。
//点击按钮,直接完成
public void onBack(View v){finish();
}
  1. 在MyNativeModule原生模块中去实现Activity。
//方法不能返回值 因为被调用的原生代码是异步的 原生代码执行结束之后只能通过回调函数或者发送消息给RN
@ReactMethod
public void rnCallNative(String msg){Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();Intent intent = new Intent(mContext,MyActivity.class);  //创建一个意图,意图是android进程之间、线程之间、交换数据的载体intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    //一定要加上这句mContext.startActivity(intent);
}

2.3 RN 应用 Promise 机制与安卓原生代码通信

使用Promise机制也是RN与原生通信的一种方式。在原生代码的MyNativeModule文件中创建桥接方法,当桥接的原生方法的最后一个参数是一个Promise对象,那么该方法会返回一个JS的Promise对象给与之对应的js方法。与上文类似,需要暴露给RN的方法不能有返回值,并且要以注释@ReactMethod标识。

@ReactMethod
public void rnCallNative_promise(String msg,Promise promise){Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();//得到组件名称String componentName = getCurrentActivity().getComponentName().toString();promise.resolve(componentName);
}

在RN中创建一个方法,这个方法内部使用NativeModules组件来调用原生模块提供的名称,进而找到要调用的原生方法。原生方法最后一个参数是一个promise,所以在js中用.then的方法实现即可。

callAndroid_promise(){NativeModules.ToastModule.rnCallNative_promise('promise调用原生').then((msg) => {console.log('promise收到消息:'+msg);}).catch((err)=>{console.log(err);})
}

渲染方法中,调用方法。

<Text style={styles.welcome} onPress={this.callAndroid_promise.bind(this)}>Promise通信</Text>
....
welcome: {fontSize: 16,textAlign: 'left',margin: 10
}

2.4 RN 应用 callback 回调方式与安卓原生代码通信

在原生模块中暴露一个桥接方法给RN调用,参数传入一个成功的回调和一个失败的回调。

@ReactMethod
public void measureLayout(Callback errorCallback,Callback successCallback){try {successCallback.invoke(100,100,200,200); //调用回调函数,返回结果}catch (IllegalViewOperationException e){errorCallback.invoke(e.getMessage());}
}

在js中实现回调方法。同样是通过NativeModules组件寻找到桥接名称ToastModule,进而找到想要调用的方法。拿到返回的参数,做功能处理。

callAndroid_callback(){NativeModules.ToastModule.measureLayout((msg)=>{console.log(msg);},(x,y,width,height)=>{console.log('x坐标:'+x+'y坐标:'+y+'高:'+height+'宽'+width);})
}

在使用回调函数时会呈现出某些缺点,比如说每次调用只应当调用一次,多次调用可能会出现意想不到的结果,并且用这种方法安卓原生代码是无法主动发送信息给RN侧的。

三、RN与IOS通信

首先 RN 与 IOS 通信,在原生端需创建一个bridge ,并遵守协议。

#import <React/RCTBridgeModule.h>
@interface PushModule : NSObject<RCTBridgeModule>

其次,在@implementation中导出 Module

@implementation PushModule
RCT_EXPORT_MODULE()

有以下3种通信方式。

3.1 定义导出的方法名

RCT_EXPORT_METHOD(pushEvent:(NSString *)event callback:(RCTResponseSenderBlock)callback){NSLog(@"----对React Native提供调用方法,Callback---%@",event);NSString *callbackData = @"原生数据被RN调用"; //准备回调回去的数据callback(@[[NSNull null],callbackData]);
}

定义一个方法后,RN 就可通过NativeModules获取到对于 Module后调用相应方法,event是 RN 传给 IOS 的值,IOS 这边可通过 callback 这个 block 回调给 RN 数据。

callBackEvent (){NativeModules.PushModule.pushEvent(('RN->原生的数据'),(error, events) => {if (error) {console.log(error);}else {alert(events)}})
}

3.2 promise 实现回调函数

static RCTPromiseResolveBlock _resolve;//成功回调
static RCTPromiseRejectBlock _reject;//失败回调RCT_REMAP_METHOD(pushPromisesEvent,resolver:(RCTPromiseResolveBlock)resolverejecter:(RCTPromiseRejectBlock)reject){_resolve = resolve;_reject = reject;}//异步回调函数
+(void) handleResult:(id)result{//原生Promises数据被RN调用if ([result isEqualToString:@"获取数据成功"]) {_resolve(@[result]);}else{//返回错误信息NSError *error=[NSError errorWithDomain:result code:101 userInfo:nil];_reject(@"no_events", @"There were no events", error);}
}

RN 侧方法调用。

NativeModules.PushModule.pushPromisesEvent().then((events)=>{
alert(events+1111)
}).catch((e)=>{
// alert(e)console.log("错误信息------"+e);})
}

3.3 继承 RCTEventEmitter 类

#import <React/RCTEventEmitter.h>
#import <React/RCTBridgeModule.h>
@interface PushModule : RCTEventEmitter<RCTBridgeModule>

.m 的实现中有几个继承方法需要实现。

//IOS 回传给 RN 的通知方法
- (NSArray*)supportedEvents{return @[@"Notice_name"]
}- (void)startObserving
{[PushTool sharedPushTool].isReady = YES;[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(notice:)name:@"event-notice"object:nil];
}-(void)notice:(NSNotification*)notification
{NSDictionary*obj = notification.object;[self sendEventWithName:@"Notice_name" body:obj];
}

在 RN 侧实施监听。

var module = new NativeEventEmitter(NativeModules.PushModule);
module.addListener('Notice_name',(data)=>this.message(data));

四、拓展阅读

  • 《iOS开发进阶(八):ipa应用唤起并跳转至指定页面》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/738876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode hot 100 —— 哈希表 by python

什么是哈希表 散列表&#xff08;Hash table&#xff0c;也叫哈希表&#xff09;&#xff0c;是根据关键码值(Key和value)而直接进行访问的数据结构。也就是说&#xff0c;它通过把关键码值映射到表中一个位置来访问记录&#xff0c;以加快查找的速度。这个映射函数叫做散列函…

快速排序和堆排序模板总结

堆排序以及快速排序模板 堆排序使用&#xff0c;215.数组中的第k个最大元素&#xff1a;https://leetcode.cn/problems/kth-largest-element-in-an-array 快速排序使用&#xff0c; 75.颜色分类&#xff1a; https://leetcode.cn/problems/sort-colors/ 堆排序模板 public …

【AI学习指南】九、PaddlePaddle自然语言处理-PaddleNLP SKEP情感分析定制化训练(万字长文附代码)

目录 加载预训练模型到指定位置 加载分词器 准备数据集 train.tsv 文件内容示例: dev.tsv 文件

第一次Python小练习题目

1.打印某学校的校训&#xff0c;具体内容如下所示&#xff1a; ****************************** 勤奋 严谨 求实 创新 ****************************** 注意: 第一行和最后一行各有 30 个*号。 答案&#xff1a; school_strs "勤奋 严谨 求实 创新&q…

8.找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p "…

申请选择商家转账到零钱流程怎样的

商家转账到零钱是什么&#xff1f; 【商家转账到零钱】可以说是【企业付款到零钱】的升级版&#xff0c;商家转账到零钱可以为商户提供同时向多个用户微信零钱转账的能力&#xff0c;支持分销返佣、佣金报酬、企业报销、企业补贴、服务款项、采购货款等自动向用户转账的场景。…

如何关闭微软的Edge浏览器右击提示的:“使用copilot重写“的提示?

最近在使用微软的edge浏览器写文档的时候&#xff0c;总是不小心右击鼠标&#xff0c;提示 有时候挺烦人的&#xff0c;那怎么关闭呢&#xff1f; 打开edge浏览器的设置 在设置中搜索AI&#xff0c;并关闭AI书写的选项就好了 这样就可以获得一个干净的界面了&#xff0c;不…

微信小程序重新加载当前页面、刷新当前页面

重新加载页面 使用wx.reLanuch&#xff08;&#xff09;&#xff0c;url: 路径当前页面跳转, 页面所有数据重新初始化&#xff0c;已配置的数据不会保存 wx.reLaunch({url: /pages/orders/createOrder/createOrder, // 当前页面的路径}) reLanuch()的方法&#xff0c;会有一个…

向指定接口上传文件

post请求&#xff0c;参数为接口地址&#xff0c;文件的绝对路径&#xff0c;例如&#xff1a;D:/files/a.txt&#xff0c; 返回结构如下&#xff1a; {"code": 200,"message": "成功","data": "1231312313","ok&quo…

什么是APP封装?APP封装有什么途径?APP封装如何实现?

APP封装是形成APP成本最低的一种方式。你只需要拥有一个手机端的网址就可以通过一些技术处理封装成一个跨iOS和Android的APP&#xff0c;这个过程往往只需要几分钟。既节省时间又能节省开发的成本资金&#xff0c;所以接下来就介绍一下大家都比较关心的怎么给手机网站封装打包成…

基于pytest的证券清算系统功能测试工具开发

需求 1.造测试数据&#xff1a;根据测试需要&#xff0c;自动化构造各业务场景的中登清算数据与清算所需起来数据 2.测试清算系统功能&#xff1a; 自动化测试方案 工具设计 工具框架图 工具流程图 实现技术 python, pytest, allure, 多进程&#xff0c;mysql, 前端 效果 测…

探索 PostgreSQL 的高级数据类型 - 第 二 部分

范围类型 范围类型提供了一种简洁的方式来表示单个数据库字段中的值范围。它们在从时间数据到数字间隔的各种领域中都有应用。在本篇博客文章中&#xff0c;我们将通过 DML/SQL 语句和 Navicat for PostgreSQL 16 来深入了解它们的使用&#xff08;以及好处&#xff01;&#…

STM32存储左右互搏 SPI总线读写SD/MicroSD/TF卡

STM32存储左右互搏 SPI总线读写SD/MicroSD/TF卡 SD/MicroSD/TF卡是基于FLASH的一种常见非易失存储单元&#xff0c;由接口协议电路和FLASH构成。市面上由不同尺寸和不同容量的卡&#xff0c;手机领域用的TF卡实际就是MicroSD卡&#xff0c;尺寸比SD卡小&#xff0c;而电路和协…

C/C++ 人们自行构建高性能反射框架,应该怎么设计比较好。

在 C/C 之中默认提供的 “RTTI” 运行时类型信息反射机制过于脆弱&#xff0c;基本就等于没什么卵用&#xff0c;但在 C/C 11 之前模板元编程不是那么强大的时候&#xff0c;还是有那么一点点作用。 我们通常利用RTTI反射T的类型或其泛型类型&#xff08;即T的T&#xff09;&am…

数学建模-多目标规划算法(美赛建模)

单目标优化的情况下&#xff0c;只有一个目标&#xff0c;任何两解都可以依据单一目标比较其好坏&#xff0c;可以得出没有争议的最优解。 多目标化与传统的单目标优化相对。多目标优化的概念是在某个情景中在需要达到多个目标时&#xff0c;由于容易存在目标间的内在冲突&…

7 BUILD.gn文件怎么写,Gn + Ninja编译一个Hello world程序的例子Demo

BUILD.gn文件怎么写&#xff0c;Gn Ninja编译一个Hello world程序的例子Demo 作者将狼才鲸创建日期2024-03-11 Ninja安装流程见&#xff1a;一个能直接运行的Ninja例子&#xff0c;build.ninja文件怎么写&#xff1f;Gn安装流程见&#xff1a;Ubuntu18.04下安装Gn软件 这是一…

webpack如何去自定义一个Loader?(大白话,so easy!)

文章目录 关注小白菜&#xff0c;前端变更菜&#xff0c;不定期更新csdn&#xff0c;内容不定看心情随便写点&#xff0c;因为近期在面试&#xff0c;所以整理一下写点笔记&#xff0c;希望可以帮到初中级的同学们&#xff0c;加油&#xff0c;奥里给&#xff01;&#xff01;&…

生成验证码图片

引入依赖包 <!-- 图形验证码 --> <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency> 配置DefaultKaptcha类 类方法配置了验证码的生成格式…

目标检测数据集:手机顶盖焊缺陷检测数据集

✨✨✨✨✨✨目标检测数据集✨✨✨✨✨✨ 本专栏提供各种场景的数据集,主要聚焦:工业缺陷检测数据集、小目标数据集、遥感数据集、红外小目标数据集,该专栏的数据集会在多个专栏进行验证,在多个数据集进行验证mAP涨点明显,尤其是小目标、遮挡物精度提升明显的数据集会在该…

std::thread 的构造-源码解析

std::thread 的构造-源码解析 我们这单章是为了专门解释一下 std::thread 是如何构造的&#xff0c;是如何创建线程传递参数的&#xff0c;让你彻底了解这个类。 我们以 MSVC 实现的 std::thread 代码进行讲解。 std::thread 的数据成员 了解一个庞大的类&#xff0c;最简单…