React-native呼叫Android原生模組
準備工作:具體詳情參考React-Native官方文件
IDE: WebStorm 和Android Studio(webstorm不支援java高亮,所以用AS輔助下)
demo放到github上了,有需要的可以參考一下. 下載demo
1.為什麼呼叫原生的一些東西?
有時候應用程式需要訪問平臺API,React Native目前還沒有相應的模組。也許你想重用一些現有的Java程式碼,而不必用JavaScript重新實現它,或者編寫一些高效能,多執行緒的程式碼,例如影象處理,資料庫或任何數量的高階擴充套件。
我們設計了React Native,因此您可以編寫真實的本機程式碼並訪問平臺的全部功能。這是一個更高階的功能,我們不希望它成為通常開發過程的一部分,但它存在必不可少。如果React Native不支援您需要的本機功能,您應該能夠自己構建它。
2.建立個Toast模組做為示例:
我們首先建立一個本地模組。本地模組是一個Java類,通常擴充套件ReactContextBaseJavaModule
該類並實現JavaScript所需的功能。我們的目標是能夠使用ToastExample.show('Awesome', ToastExample.SHORT);
JavaScript 編寫在螢幕上顯示簡短toast。
2.1:建立一個名為ToastModule.java
,其內容如下:
import android.widget.Toast; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; /** * Description: * Created by song on 2018/7/3. * email:
[email protected] */ public class ToastModule extends ReactContextBaseJavaModule { private static final String DURATION_SHORT_KEY="SHORT"; private static final String DURATION_LONG_KEY="LONG"; public ToastModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "ToastExample"; } @Nullable @Override public Map<String, Object> getConstants() { final Map<String,Object> constants=new HashMap<>(); constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT); constants.put(DURATION_LONG_KEY,Toast.LENGTH_LONG); return constants; } @ReactMethod public void show(String message,int duration){ Toast.makeText(getReactApplicationContext(),message,duration).show(); }
ReactContextBaseJavaModule
要求實現一個被呼叫的方法getName
。此方法的目的是NativeModule
在JavaScript中返回表示該類的字串名稱。所以在這裡我們將呼叫它,ToastExample
以便我們可以通過React.NativeModules.ToastExample
JavaScript 訪問它。
@Override
public String getName() {
return "ToastExample";
}
一個可選的方法呼叫getConstants
返回暴露給JavaScript的常量值。它的實現不是必需的,但對於需要同步從JavaScript到Java進行通訊的關鍵預定義值非常有用。
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
return constants;
}
要向JavaScript公開方法,必須使用Java方法註釋Java方法@ReactMethod
。橋接方法的返回型別總是如此void
。React Native橋是非同步的,因此將結果傳遞給JavaScript的唯一方法是使用回撥或發射事件(請參見下文)。
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
3.註冊模組
Java中的最後一步是註冊模組; 這發生在createNativeModules
你的應用程式包中。如果模組未註冊,則無法從JavaScript獲得。
建立一個名為CustomToastPackage.java
inside android/app/src/main/java/com/your-app-name/
folder 的新Java類,其內容如下:
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;
/**
* Description:
* Created by song on 2018/7/3.
* email:[email protected]
*/
public class CustomToastPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules=new ArrayList<>();
modules.add(new ToastModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
該包需要getPackages
在MainApplication.java
檔案的方法中提供。該檔案存在於react-native應用程式目錄中的android資料夾下。該檔案的路徑是:android/app/src/main/java/com/your-app-name/MainApplication.java
。
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new CustomToastPackage()
);
}
4.把原生模組包裝到js模組中:
在react-native工程下,建立一個js檔案;
檔案中新增:
import {NativeModules} from 'react-native';
module.exports = NativeModules.ToastExample;
5.在App.js中呼叫原生模組:
//從android.js中匯入
import ToastExample from './android';
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}>
//呼叫
<Text style={styles.welcome} onPress={()=>ToastExample.show("js中點的啊",ToastExample.SHORT)}>
呼叫原生Toast!
</Text>
</View>
);
}
}