按照个人理解,RN和Android原生混合开发分为两种情况,第一种是以RN为主,原生为辅的混合开发,第二种则是以原生为主RN为辅的混合开发,最近几篇文章尽量以这两种情况区分,做一个大概整体的梳理
这篇文章主要讲一下以RN为主 调用Android原生函数的基本使用方法,先上图
下面看具体流程:
1,新建项目,在命令行初始化一个RN项目,这一步比较简单 就不贴图了
2、 Android原生部分代码,分三步:实现ReactContextBaseJavaModule,添加到NativeModules,Application中注册,下面看详细代码
继承ReactContextBaseJavaModule类,实现getName()方法,返回暴露给RN的模块名字,并且在这个类中实现自己需要的方法(比如下面例子中的getResult()和jumpActivity())
package com.demo2.rn_module;
import android.app.Activity;
import android.content.Intent;
import com.demo2.SecondActivity;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class AndroidTest extends ReactContextBaseJavaModule implements ActivityEventListener {
public AndroidTest(ReactApplicationContext reactContext) {
super(reactContext);
}
//用ReactNative注解,标示此方法是可以被RN调用的
@ReactMethod
public void getResult(int a, int b, Promise promise) {
int c = a + b;
promise.resolve(c);
}
//用ReactNative注解,标示此方法是可以被RN调用的
@ReactMethod
public void jumpActivity() {
Intent intent = new Intent(getCurrentActivity(), SecondActivity.class);
getCurrentActivity().startActivity(intent);
}
//返回模块名字,方便在RN中引用
@Override
public String getName() {
return "AndroidTest";
}
//这两方法是ActivityEventListener接口中的,方便处理一些由此模块跳转后返回的回调事件
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
}
@Override
public void onNewIntent(Intent intent) {
}
}
实现ReactPackage接口,实现里面的方法,将刚才新建的AndroidTest这个Module添加到NativeModules里面
package com.demo2.rn_module;
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 AndroidPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> list = new ArrayList<>();
//添加到NativeModules
AndroidTest androidTest = new AndroidTest(reactContext);
list.add(androidTest);
return list;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
继承Application并实现ReactApplication,将刚才AndroidPackage 注册到RN,如下代码:
package com.demo2;
import android.app.Application;
import com.demo2.rn_module.AndroidPackage;
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 AndroidPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
3、RN中的代码
新建一个AndroidConnent.js,这个JS文件就是为了导包用的,要不从引用的地方导太麻烦
import {NativeModules} from 'react-native';
export default NativeModules.AndroidTest;
RN页面实现
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, Button, View, Dimensions, ToastAndroid} from 'react-native';
import AndroidTest from "./AndroidConnent";
const ScreenWidth = Dimensions.get("window").width;
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> {
render() {
return (
<View style={styles.container}>
<Button
style={{width: ScreenWidth}}
title="RN调用Android原生方法"
onPress={this.onClick}
/>
<Button
style={{width: ScreenWidth}}
title="RN跳转Android原生界面"
onPress={this.jump}
/>
</View>
);
}
onClick() {
/*AndroidTest是Android原生中getName中返回的字符串*/
AndroidTest.getResult(1, 2).then(result => {
ToastAndroid.show(result + "", 1000);
})
}
jump() {
AndroidTest.jumpActivity();
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
以上就是RN中调用Android原生模块中函数的基本流程,简单的RN跳转原生界面也是一样的流程,只需要在ReactContextBaseJavaModule的子类AndroidTest中多加一个jumpActivity()方法就可以了,携带参数的情况也是一样的,最终传递参数还是在原Android原生里面传递的
还有一个Android和RN混合开发的demo,需要的可以下载参考,demo包含了
1、Android加载RN页面
2、Android调用RN函数
3、RN调用Android函数
传送门
<完>