咱们在用RN开发App的时候,有时候须要用到一些原生模块,好比:分享、第三方登陆等。在RN的官方文档是这样谈到的:java
“有时候App须要访问平台API,但在React Native可能尚未相应的模块。或者你须要复用一些Java代码,而不想用JavaScript再从新实现一遍;又或者你须要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者一些高级扩展等等。 ”react
咱们所要作的事情很简单,在RN组件中,点击一个按钮,触发原生模块中的咱们所编写的事件,获取当前时间并显示android
以下图git
在android/app/src/main/java/下建立com.myNativeModule这样一个package(项目结构以下图)github
在android/app/src/main/java/com/myNativeModule目录下新建一个TextModule.java。在这个类中,咱们实现了具体的逻辑功能。数据库
package com.myNativeModule; import android.content.Context; import android.util.Log; import android.widget.Toast; import java.text.SimpleDateFormat; import java.util.Date; public class TextModule { public void getTime(Context ctx) { SimpleDateFormat formatDate=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); Date date=new Date(System.currentTimeMillis()); //获取当前时间 String s=formatDate.format(date); Log.e("HHH",s); Toast.makeText(ctx,s,Toast.LENGTH_SHORT).show(); } }
实现了获取当前时间功能后,咱们接下来就要暴露给React Native,以供js调用。
react-native
接下来咱们就要向React Native暴露接口以及作一些数据交互部分的操做。为了暴露接口以及进行数据交互咱们须要借助React Native的ReactContextBaseJavaModule 类。
(在android/app/src/main/java/com/myNativeModule目录下新建一个MyNativeModule.java。)
android-studio
package com.myNativeModule; import android.content.Context; 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 { private Context mContext; public MyNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } // 重载了getName()方法,用来暴露咱们原生模块的名字 @Override public String getName() { return "MyNativeModule"; // 返回的这个名字是必须的,是Native暴露给JS的名字 } // 经过@ReactMethod注解来暴露接口,这样以来咱们就能够在js文件中经过MyNativeModule.rnCallNative()来调用咱们暴露给RN的接口了 // 不能有返回值,由于被调用的原生代码是异步的,原生代码执行结束后只能经过回调函数或者发送消息给RN @ReactMethod public void rnCallNative(String msg) { new TextModule().getTime(mContext); } }
为了向React Native注册咱们刚才建立的原生模块,咱们须要实现ReactPackage,ReactPackage主要为注册原生模块所存在,只有已经向React Native注册的模块才能在js模块使用。
(在android/app/src/main/java/com/myNativeModule目录下新建一个MyReactPackage.java。)
多线程
package com.myNativeModule; 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 com.myNativeModule.MyNativeModule; 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)); return modules; } public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
在上述代码中,咱们实现一个ReactPackage,接下来呢,咱们还须要在android/app/src/main/java/com/nativetest/MainApplication.java中注册咱们的MyReactPackage:
app
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new MyReactPackage() // 在这里将咱们刚才建立的MyReactPackage添加进来 ); }
原生模块注册完成以后呢,咱们接下来就须要为咱们的原生模块导出一个js模块,这样作的目的是在实际的项目中,为了更好的可读性和可维护性以及更方便地使用它。
在RN根目录的js/native/下建立一个native.js文件
import { NativeModules } from 'react-native'; export { MyNativeModule: NativeModules.MyNativeModule }
接下来,咱们就能够在其余地方经过下面的方式来使用所导出的这个模块了。
import React, { Component } from 'react'; import { StyleSheet, View, Button } from 'react-native'; import { MyNativeModule } from './native'; type Props = {}; export default class App extends Component<Props> { render() { return ( <View style={styles.container}> <Button onPress={this.call_button.bind(this)} title="点击调用原生模块方法" /> </View > ); } call_button() { MyNativeModule.rnCallNative('调用原生模块中的方法成功'); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', } });
测试结果以下:
在上边的Demo中,主要是实现原生模块TestModule.java,而后咱们在要被RN调用的方法中调用原生类中的方法。对于N多原生类均可以直接粘贴复制过来。这样就能够实现调用复杂方法实现强大功能了。
Demo地址https://github.com/codeprolin/RN_Native_Android