IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> React Native与原生通信 -> 正文阅读

[移动开发]React Native与原生通信

一、RN与安卓通信

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();
    }

(3)在原生代码中创建一个类实现接口ReactPackage包管理器,并且把第二步已经创建好的类加入到原生模块列表里。

public class MyReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new MyNativeModule(reactContext));
        return modules;
    }
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

(4)将创建好的包管理器添加到ReactPackage列表里,也就是MainApplication代码中,在类里找到方法getPackages方法,将包管理器添加进去。

 @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              new MyReactPackage()
      );
    }

(5)在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、RN用消息机制方式与安卓原生代码切换

在原生代码中添加一个按钮,当用户从RN界面调用原生代码就会进入到原生代码开发的界面中,而点击原生代码中的按钮就会返回到RN界面
(1)在与MainApplication同级的目录下创建一个MyActivity,会自动生成一个自动布局文件activity_my做布局的工作
(2)打开布局文件,将左下角的Design切换成Text文件,为原生界面创建一个按钮并且布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:layout_width = "match_parent"
    android:layout_height="match_parent"
    xmlns:android = "http://schemas.android.com/apk/res/android"
    >

    <Button
        android:text="goBack"
        android:onClick="onBack"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</RelativeLayout>

(3)回到新创建的MyActivity代码,实现onBack方法

  //点击按钮,直接完成
    public void onBack(View v){
        finish();
    }

(4)在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);
    }

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>

给Text组件设置样式

 welcome: {
        fontSize: 16,
        textAlign: 'left',
        margin: 10
    }

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种通信方式

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)
		}
	})
}

2、promise实现的回调函数

static RCTPromiseResolveBlock _resolve;//成功回调
static RCTPromiseRejectBlock _reject;//失败回调

RCT_REMAP_METHOD(pushPromisesEvent,
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(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、继承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:self
                                           selector:@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));

Refs:
RN与原生通讯(安卓篇)
RN 端 与IOS原生的交互通信

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 01:04:20  更:2022-09-30 01:05:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 0:33:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码