React Native 中調用原生 android 模塊 Toast 例子及說明
react-native-android-toast
react-native 調用原生 android 模塊 Toast 學習筆記
參考官方文檔初始化一個react-native項目
react-native init androidToast
生成如下目錄:
運行命令查看項目
react-native run-android
如圖:
接入Android原生模塊
按照官方的說法,第一步需要創建一個java類 本例中為:ToastModule ,并繼承 ReactContextBaseJavaModule ,然后復寫 getName() 方法,其返回值,就是在 react-native 中引用的 組件名稱
復寫 getConstants() 方法可以返回一些 常量 用于react-native中調用,官方文檔中 return "ToastAndroid" 這個名稱在原生的組件中已經存在,返回相同的名稱將會沖突,so:改個名字吧!!
<p>@ReactMethod 注解:用于java返回一個 react-native 中可調用的 方法 ,其不能有返回值所以使用 void</p>注冊模塊:創建java類 本例中為:ExampleReactPackage ,實現 ReactPackage 接口
復寫createJSModules() , createViewManagers() 方法,返回 Collections.emptyList() 空集合
createNativeModules() 方法中添加我們需注冊的模塊對象, new ToastModule() ,并返回模塊集合
添加已注冊模塊對象到返回集合中,向react-native拋出模塊,如:第三步
在react-native中調用,如:第四步
android目錄結構
注意:引入包的名稱不要弄錯了
Java & ReactNative 基本類型對照
Java | RN |
---|---|
Boolean | Bool |
Integer | Number |
Double | Number |
Float | Number |
String | String |
Callback | function |
ReadableMap | Object |
ReadableArray | Array |
第一步:創建模塊類
在androidtoast目錄下,創建一個ToastModule.java的類
package com.androidtoast; //包名
import android.widget.Toast; //引入調用的類
import com.非死book.react.bridge.ReactApplicationContext;
import com.非死book.react.bridge.ReactContextBaseJavaModule;
import com.非死book.react.bridge.ReactMethod;
import com.非死book.react.uimanager.IllegalViewOperationException;
import java.util.Map;
import java.util.HashMap;
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);
}
// 復寫方法,返回react-native中調用的 組件名
@Override
public String getName() {
return "ToastNative";
}
// 復寫方法,返回常量
@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注解返回react-native中可調用的 方法
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
}</code></pre>
第二步:注冊模塊
在androidtoast目錄下,創建一個ExampleReactPackage.java的類
package com.androidtoast;
import android.widget.Toast;
import com.非死book.react.bridge.NativeModule;
import com.非死book.react.bridge.ReactApplicationContext;
import com.非死book.react.bridge.ReactMethod;
import com.非死book.react.ReactPackage;
import com.非死book.react.bridge.JavaScriptModule;
import com.非死book.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExampleReactPackage implements ReactPackage {
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ToastModule(reactContext));
return modules;
}
}</code></pre>
第三步:添加注冊類
添加到 MainApplication.java 中的 getPackages() 方法中
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(), // 這個是自動創建
new ExampleReactPackage() // 這個類是我們創建的
);
}
項目結構如下:

Java部分的代碼就結束了,再次提醒下:包名啊!!不要弄錯了!!!
第四步:修改react-native代碼引入原生模塊
修改index.android.js
- 引入react-native所需模塊 NativeModules
- 獲取導出組件 NativeModules.ToastNative
- 調用方法 show()
修改了下index.android.js文件,代碼如下:
/**
- Sample React Native App
- https://github.com/非死book/react-native
- @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
NativeModules
} from 'react-native';
let toast = NativeModules.ToastNative;
export default class androidToast extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>react-native 調用android原生模塊</Text>
<TouchableOpacity onPress={()=>{
toast.show('Toast message',toast.SHORT);
}}>
<Text style={styles.btn}>Click Me</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
title:{
fontSize:16,
},
btn:{
fontSize:16,
paddingVertical:7,
paddingHorizontal:10,
borderColor:'#f00',
borderWidth:1,
borderRadius:5,
marginTop:10,
color:'#f00'
}
});
AppRegistry.registerComponent('androidToast', () => androidToast);</code></pre>
運行程序
react-native run-android
效果如下:

react-native回調函數
*java中提供了一個 Callback 的數據類型對應了react-native中的 function *
具體操作就是在@ReactMethod注解的返回函數中 添加 類型 為 Callback 的參數,并通過 invoke(...params) 調用
RN中通過調用show方法時提供對應的回調函數就可以了, :smile:
-
修改 ToastModule.java 代碼中 show() 方法,添加回調
注意引包!! import com.非死book.react.bridge.Callback;
// 說明下:count,flag是我自定義的變量
@ReactMethod
public void show(String message, int duration ,Callback successCallback, Callback errorCallback) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
// 通過invoke調用,隨便你傳參
if(flag) successCallback.invoke("success", ++count);
else errorCallback.invoke("error", ++count);
flag = !flag;
}</code></pre>
-
修改 index.android.js 中調用函數
<TouchableOpacity onPress={()=>{
toast.show('Toast message',toast.SHORT,(message,count)=>{console.log("==",message,count)},(message,count)=>{console.log("++",message,count)});
}}>
:ok_hand: ,試試看吧~~
觸發事件
首先我們定義一個發送事件的方法
private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params){
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
引包
import javax.annotation.Nullable;
import com.非死book.react.bridge.Arguments;
import com.非死book.react.bridge.WritableMap;
import com.非死book.react.bridge.ReactContext;
import com.非死book.react.modules.core.DeviceEventManagerModule;</code></pre>
繼續改造 show 方法,添加參數,并調用預先定義的方法
// 靜態方法
WritableMap map = Arguments.createMap();
map.putBoolean("boolean",true);
map.putDouble("double",0.003);
map.putString("string","string");
sendEvent(this.reactContext, "eventName",map);
改造 index.android.js 啦 ,添加事件監聽,這里的 eventName 就是我們 sendEvent 中定義的事件名稱
componentWillMount(){
DeviceEventEmitter.addListener('eventName',(e)=>{
console.log(e)
});
}
效果如下:

曾走過的路
曾想在返回的方法中定義一個 Object 類型的變量,但pa! 報錯了!!不支持滴,請查看類型對應表格
cloudn't find argument class : Object
參照官方文檔時,各種類找不到,瞬間醉了!
# 百度吧,一般不管用
stackoverflow,Google 有時可以搜到,尼瑪!英文。。。
github
react-native 源碼 !!!這里面有個ReactAndroid
的目錄就是各種Java
類啦
react-native/ReactAndroid/src/main/java/com/非死book/
https://github.com/非死book/react-native</code></pre>

參考文檔
來自:https://github.com/Xing-He/react-native-android-toast/blob/master/README.md