《React-Native系列》2、RN与native交互与数据传递

颜宸
2023-12-01

RN怎么与native交互的呢?

下面我们通过一个简单的Demo来实现:RN页面调起Native页面,Native页面选择电话本数据,将数据回传给RN展示。

首先是 Native侧

 1、MainActivity 

package com.rnandroid01;

import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;

import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "RNAndroid01";
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode!=200 || resultCode!=RESULT_OK) return;
        Uri contactData = data.getData();

        Cursor cursor = managedQuery(contactData, null, null, null, null);
        cursor.moveToFirst();
        String num = getContactPhone(cursor);


        //下面的话  就是将num发送给rn侧 需要调用nativeModule对象里面的方法

        MainApplication.getMyReactPackage().myNativeModule.sendMsgToRn(num);

    }

   //这个是Native代码,与RN其实没什么关系
    private String getContactPhone(Cursor cursor) {
        // TODO Auto-generated method stub
        int phoneColumn = cursor
                .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
        int phoneNum = cursor.getInt(phoneColumn);
        String result = "";
        if (phoneNum > 0) {
            // 获得联系人的ID号
            int idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID);
            String contactId = cursor.getString(idColumn);
            // 获得联系人电话的cursor
            Cursor phone = getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="
                            + contactId, null, null);
            if (phone.moveToFirst()) {
                for (; !phone.isAfterLast(); phone.moveToNext()) {
                    int index = phone
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                    int typeindex = phone
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
                    int phone_type = phone.getInt(typeindex);
                    String phoneNumber = phone.getString(index);
                    result = phoneNumber;
                }
                if (!phone.isClosed()) {
                    phone.close();
                }
            }
        }
        return result;
    }

}

2、MainApplication

package com.rnandroid01;

import android.app.Application;
import android.util.Log;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {


    private static final MyReactPackage myReactPackage=new MyReactPackage();

    public static MyReactPackage getMyReactPackage() {
        return myReactPackage;
    }

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    protected boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

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

  @Override
  public ReactNativeHost getReactNativeHost() {
      return mReactNativeHost;
  }
}

3、MyReactPackage

package com.rnandroid01;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyReactPackage implements ReactPackage {

    public MyNativeModule myNativeModule;

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        myNativeModule=new MyNativeModule(reactContext);
        modules.add(myNativeModule);
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

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

4、MyNativeModule

package com.rnandroid01;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.Toast;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;


public class MyNativeModule extends ReactContextBaseJavaModule {

    private ReactApplicationContext mContext;

    public MyNativeModule(ReactApplicationContext reactContext) {
        super(reactContext);

        mContext = reactContext;
    }

    @Override
    public String getName() {
        //一定要有这个名字的 在rn代码里面是需要这个名字来调用该类的方法的
        return "MyNativeModule";
    }

    //函数不能有返回值,因为被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数或者发送消息给rn那边

    //有一个错误

    @ReactMethod
    public void rnCallNative(String msg) {
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();


//        Intent intent = new Intent(mContext, MyActivity.class);
//        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//一定要加上这句 否则报错
//        mContext.startActivity(intent);


        Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
        Bundle bundle = new Bundle();
        mContext.startActivityForResult(intent,200,bundle);


    }

    public void sendMsgToRn(String msg){
        //将消息msg发送给RN侧
        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage",msg);

    }

}



在RN侧

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  NativeModules,
  DeviceEventEmitter,
  View
} from 'react-native';

class RNAndroid01 extends Component {
 

  componentWillMount(){
    DeviceEventEmitter.addListener('AndroidToRNMessage',this.handleAndroidMessage);
  }

  componentWillunMount(){
     DeviceEventEmitter.remove('AndroidToRNMessage',this.handleAndroidMessage);
  }


  handleAndroidMessage=(msg)=>{
     //RN端获得native端传递的数据
     console.log(msg);
  }


  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}
        onPress={this.CallAndroid}
        >
          Welcome to React Native!RN与Android的通信
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Shake or press menu button for dev menu
        </Text>
      </View>
    );
  }


  CallAndroid=()=>{
    NativeModules.MyNativeModule.rnCallNative('rn调用原生模块的方法-成功啦');
  }
}


上面的例子实现了RN与Native端的交互及数据传递。


重点使用了React Native的RCTDeviceEventEmitter,通过消息机制来实现。

好了,RN与native的交互还可以通过Promise和Callback回调方式实现,我们下篇文章再看。


 类似资料: