咱們在用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