ReactNative与Android的交互

1 RN调用Native方法

  • 1、创建交互类Module,继承ReactContextBaseJavaModule
  • 2、创建package,实现ReactPackage的方法,添加步骤1创建的交互类Module到package内;
  • 3、添加创建的自定义package到ReactNativeHost中的getPackages方法中,向ReactNative注册原生模块;
1.1 导出Native端的showInfo提示方法

Native端导出

public class RNInterractModule extends ReactContextBaseJavaModule {

    private ReactContext mReactContext;

    public RNInterractModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.mReactContext = reactContext;
    }

//导出的模块名字
    @Override 
    public String getName() {
        return "RNInterractModule";
    }
    
    //==============1、提示==============
    @ReactMethod
    public void showInfo(String info){
        Toast.makeText(getReactApplicationContext(),info,Toast.LENGTH_SHORT).show();
    }
}

复制代码

添加Module到自定义package:

public class RNInterractPackage implements ReactPackage{
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new RNInterractModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
复制代码

再添加package(此处展示完整的MainApplication方法,重写getPackages()方法中添加)


public class MainApplication extends Application implements ReactApplication{
    @Override
    public ReactNativeHost getReactNativeHost() {
        return reactNativeHost;
    }


    private ReactNativeHost reactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return true;
        }

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

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };
}
复制代码
1.2 RN端调用导出的showInfo方法:

我们在RN端把Native的方法通过一个共同的utils工具类引入,如下


import { NativeModules } from 'react-native';

//导出Native端的方法
export const { showInfo} = NativeModules.RNInterractModule;
复制代码

具体的RN页面使用时:

import { showInfo } from "../utils";

//通过Button点击事件触发
<Button
	title='1、调用Native提示'
	onPress={() => showInfo('我是原生端的提示!')}
/>
复制代码

调用效果:

1.3 RN回调Native

我们提供一个例子来模拟:目前的需求是做面包,RN端能提供面粉,但是不会做,Native端是有做面包的功能;所以我们需要先把面粉,传给Native端,Native加工好面包之后,再通过回调回传给RN端。

Native端提供方法


// 比如调用原生的方法处理图片、视频之类的,处理完成之后再把结果回传到RN页面里去
//TODO: 请务必注意 callback 并非在对应的原生函数返回后立即被执行——注意跨语言通讯是异步的,这个执行过程会通过消息循环来进行。
@ReactMethod
public void patCake(String flour, Callback successCallback,Callback errorCallback){
    try{
        //模拟异常,走reject
        if (!flour.getClass().equals(String.class)){
            throw new Exception("出错了,参数类型不匹配");
        }

        successCallback.invoke(patCakeUse(flour));
    }catch (Exception e){
        errorCallback.invoke(e.getMessage());
    }
}

//使用RN端传递的参数字符串:"",调用Native端的做面包方法,加工成面包,再回传给RN
private String patCakeUse(String flour){
    String cake = String.format("使用%s,做好了:\uD83C\uDF82\uD83C\uDF5E\uD83C\uDF5E\uD83C\uDF70\uD83C\uDF70\uD83C\uDF70",flour);
    return cake;
}
复制代码

RN端调用:

//首先工具类里先引入
export const { showInfo,patCake } = NativeModules.RNInterractModule;


//具体页面使用
<Button
	title='4、回调:使用面粉做蛋糕'
	onPress={() => patCake('1斤面粉',
		(cake) => alert(cake),
		(error) => alert('出错了' + error.message))}
	/>
复制代码

调用效果:

1.4 使用Promise回调

Native端提供方法

@ReactMethod
    public void callNameTointroduction(String name, Promise promise){
        try{
            //模拟异常,走reject
            if (!name.getClass().equals(String.class)){
                throw new Exception("出错了,参数类型不匹配");
            }

            promise.resolve(introduction(name));
        }catch (Exception e){
            promise.reject(e);
        }
    }

    private String introduction(String name){
      return String.format("我的名字叫%s,今年18岁,喜欢运动、听歌...",name);
    }
复制代码

RN端调用:

//首先工具类里先引入
export const { showInfo,patCake, callNameTointroduction} = NativeModules.RNInterractModule;

//具体页面使用
<Button
	title='5、Promise:点名自我介绍'
	onPress={
		async () => {
			try {
				let introduction = await callNameTointroduction('小明');
				showInfo(introduction);
			} catch (e) {
				alert(e.message);
			}
		}
	}
/>

复制代码

调用效果:

2 Native发送通知到RN

实现自定义的发送RN消息类RNNotificationManager

public class RNNotificationManager {
    //定义上下文
    public static  ReactContext mContext;

    //发送事件到RN端
    public static void sendRNEvent(String eventName, @Nullable WritableMap params){
        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,params);
    }
}
复制代码

我们使用静态成员变量、方法,mContext在自定义的RNInterractModule为其赋值:

public class RNInterractModule extends ReactContextBaseJavaModule {

    private ReactContext mReactContext;

    public RNInterractModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.mReactContext = reactContext;
        //赋值
        RNNotificationManager.mContext = reactContext;
    }
}
复制代码

然后就可以在需要给RN发送消息的地方调用:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                WritableMap params = Arguments.createMap();
                params.putString("message","登录成功");
                RNNotificationManager.sendRNEvent("kRNNotification_Login",params);
            }
        });
复制代码

RN端接收消息:

//添加监听
componentWillMount() {
		this.subscription = DeviceEventEmitter.addListener('kRNNotification_Login',this.updateLoginInfoText)
}
//移除监听
componentWillUnmount() {
	console.log('ActivityScene--------->', '移除通知');
	this.subscription.remove();
}
复制代码

调用展示:

3 Native向RN自定义传参
  • 在继承ReactActivity的RN入口Activity中,自定义CustomDelegate(继承ReactActivityDelegate);
  • 然后重写CustomDelegategetLaunchOptions()方法,此处的Bundle即为要传递的参数Bundle;
  • 再重写RN入口Activity的createReactActivityDelegate()方法,返回CustomDelegate实例;
  • RN端参数接收通过入口页面的this.props获取,具体可参考demo

示例:

public class ReactNativeActivity extends ReactActivity {

    private String strData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Intent intent = getIntent();
        if (intent != null){
            strData = intent.getStringExtra("msgKey");
        }
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    protected String getMainComponentName() {
        return "RNTest";
    }

    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        return new CustomDelegate(this,getMainComponentName());
    }

    //自定义ReactDelegate
    class CustomDelegate extends ReactActivityDelegate {

        private CustomDelegate(Activity activity, @Nullable String mainComponentName) {
            super(activity, mainComponentName);
        }

        @Nullable
        @Override
        protected Bundle getLaunchOptions() {
            Bundle bundle = new Bundle();
            bundle.putString("msg",strData);
            return bundle;
        }
    }
}
复制代码

4 完整Demo(包含iOS & Android)

RN-NativeTest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值