目錄
1.為什么我們需要原生模塊開發
2.開發Android原生模塊的主要流程
3.原生模塊開發實戰
1.為什么我們需要原生模塊開發?
我們在用RN開發App的時候,有時候需要用到一些原生模塊,比如:分享、第三方登錄等。在RN的官方文檔是這樣談到的:
“有時候App需要訪問平台API,但在React Native可能還沒有相應的模塊。或者你需要復用一些Java代碼,而不想用JavaScript再重新實現一遍;又或者你需要實現某些高性能的、多線程的代碼,譬如圖片處理、數據庫、或者一些高級擴展等等。 ”
2.開發Android原生模塊的主要流程
2.1 構建一個React Native Android原生模塊的流程大致分為以下三大步:
- 編寫相關的原生模塊Java代碼;
- 暴露接口與數據交互;
- 注冊與導出React Native原生模塊;
2.1 使用React Native Android原生模塊
- 在相應js組件中導入NativeModule;
- 使用對應暴露的接口方法;
3.原生模塊開發實戰
我們所要做的事情很簡單,在RN組件中,點擊一個按鈕,觸發原生模塊中的我們所編寫的事件,獲取當前時間並顯示
3.1 使用Android Studio導入android項目
如下圖

在android/app/src/main/java/下創建com.myNativeModule這樣一個package(項目結構如下圖)

3.2 編寫相關的原生模塊Java代碼
在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調用。
3.3 暴露接口與數據交互
接下來我們就要向React Native暴露接口以及做一些數據交互部分的操作。為了暴露接口以及進行數據交互我們需要借助React Native的ReactContextBaseJavaModule 類。
(在android/app/src/main/java/com/myNativeModule目錄下新建一個MyNativeModule.java。)
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);
}
}
3.4 注冊與導出React Native原生模塊
為了向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:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new MyReactPackage() // 在這里將我們剛才創建的MyReactPackage添加進來
);
}
3.5 導出一個JS模塊
原生模塊注冊完成之后呢,我們接下來就需要為我們的原生模塊導出一個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
