RN给原生传递参数
步骤:
1.用Android Studio打开一个已经存在的RN项目,即用AS打开 项目文件夹/android/build.gradle文件。
2.在Android原生这边创建一个类继承ReactContextBaseJavaModule,这个类里边放我们需要被RN调用的方法,将其封装成一个原生模块。
MyNativeModule.java代码如下:
package com.rn_protogenesis_communication;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class MyNativeModule extends ReactContextBaseJavaModule {
// 创建一个上下文,放到构造函数中,得到reactContext
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();
}
}
本类中存放我们要复用的原生方法,继承了ReactContextBaseJavaModule类,并且实现了其getName()方法,构造方法也是必须的。按着Alt+Enter程序会自动提示。接着定义了一个方法,该方法必须使用注解@ReactMethod标明,说明是RN要调用的方法。
3.在Android原生这边创建一个类实现接口ReactPackage包管理器,并把第二步创建的类加到原生模块(NativeModule)列表里。
MyReactPackage.java代码如下:
package com.rn_protogenesis_communication;
import com.facebook.react.ReactPackage;
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{
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules=new ArrayList<>();
//将我们创建的类添加进原生模块列表中
modules.add(new MyNativeModule(reactContext));
modules.add(new MyNativeCallBack(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
//返回值需要修改
return Collections.emptyList();
}
}
4.将第三步创建的包管理器添加到ReactPackage列表里(getPackage方法里)
MainApplication.java代码如下:
package com.rn_protogenesis_communication;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
//将我们创建的包管理器给添加进来
new MyReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
MainActivity.java代码如下:(无需改动)
package com.rn_protogenesis_communication;
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 "RN_Protogenesis_Communication";
}
}
5.在RN中去调用原生模块,必须import NativeModule模块。
在本Demo中需要在WebStorm修改App.js文件,需要从‘react-native’中引用‘NativeModules’,
App.js代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, NativeModules} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
export default class App extends Component<Props> {
call_button(){
NativeModules.MyNativeModule.rnCallNative('RN把值传给安卓原生');
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}
onPress={this.call_button.bind(this)}
>
React Native 调用原生方法!
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
}
});
我们将一个文本框绑定了一个事件,首先import导入NativeModule,当点击文本时将会调用call_button()方法。然后传入一个上下文对象,也就是一句话,通过调用原生方法rnCallNative( )方法来实现。
来分析一下程序运行流程:
(1)在配置文件AndroidManifest.xml中,android:name=".MainApplication",则MainApplication.java会执行。
(2)在MainApplication.java中,有我们创建的包管理器对象。程序加入MyReactPackage.java中。
(3)在MyReactPackage.java中,将我们自己创建的模块加入了原生模块列表中,程序进入MyNativeModule.java中。
(4)在MyNativeModule.java中,有我们需要被复用的原生方法rnCallNative( )。
实现数据从Android原生回调到RN前端界面
我们都知道,要被RN调用的方法必须是void 类型,即没有返回值,但是项目中很多地方都需要返回数据。那怎么实现呢?
步骤:
1.在Android原生这边创建一个类继承ReactContextBaseJavaModule,这个类里边放我们需要被RN调用的方法,将其封装成一个原生模块。
MyNativeCallBack.java代码如下:
package com.rn_protogenesis_communication;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class MyNativeCallBack extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext;
public MyNativeCallBack(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
//返回的这个名字是必须的,在rn代码中需要这个名字来调用该类的方法。
return "MyNativeCallBack";
}
//函数不能有返回值,因为被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数或者发送信息给rn那边。
@ReactMethod
public void getResult(final Callback callback){
new Thread(new Runnable() {
@Override
public void run() {
String str= "回调的数据内容";
callback.invoke(str);
}
}).start();
}
}
如图所示:我们定义一个方法,使用Callback, 在这个方法中,建立并且开启一个线程,使用callback. invoke( XXXX)实现数据向RN前端的传递。其中str为一个变量,也可以是某个类的一个变量。
2.在RN中调用。
App.js代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, NativeModules} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
export default class App extends Component<Props> {
constructor(props){
super(props);
this.state = {
global: '这是回调之前的信息',
}
}
callBack_button(){
NativeModules.MyNativeCallBack.getResult((result) => {this.setState({global:result})});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}
onPress={this.callBack_button.bind(this)}
>
React Native 调用原生方法,原生方法给RN回调!
</Text>
<Text style={styles.instructions}>{this.state.global}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: 'red',
marginBottom: 5,
},
});
当我们点击按钮时,将会调用getResult方法,并且将ReceiveData变量的值传递给RN前端的result变量中,利用setState来实现界面的更新。