主要內容:
- 關於通信的一些思考
- React Js 與 Native 之間的通信的三種方式
- React Js 與 Native 通信三種方式的比較
- React Js 與 Native 之間的通信的基本原理
一、關於通信的一些思考
1、進程間的通信:
在Android 系統中,應用是運行在由多個線程組成的進程中的,有的應用包含一個進程,有的可能會有兩個進程,甚至多個進程。Android 系統中常見的進程間通信方式有 Binder、AIDL、Messenger;
2、線程間的通信
在Android 中,線程與線程的通信方式有,Intent、Handler;
3、傳統的Js 與 Android 之間的通信
場景一般是Andoid WebView 與 頁面中加載的Js 方法之間的通信,使用 addJavascriptInterface 來實現兩者之間的通信。
比如要實現,在Js 頁面中調用 Android 中的 Toast提示,可以這樣做:
Java 端:
mWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
// 聲明一個@JavascriptInterface,
/** Show a toast from the web page */
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
在 Js 端調用如下:
<button onclick="showAndroidToast('addjavascriptinterface');">showAndroidToast</button>
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>
二、React Js 與 Native 之間的通信的三種方式
在React Js 與 Android 的通信沒有使用傳統的 addJavascriptInterface 方式,採用三種更友好的方式,分別是:
- CallBack 方式
- Promise 回調
- RCTDeviceEventEmitter 發送消息
1、CallBack 方式
主要的接口說明:
/**
* Interface that represent javascript callback function which can be passed to the native module
* as a method parameter.
*/
public interface Callback {
public void invoke(Object... args);
}
使用方法,在Android 端,在繼承ReactContextBaseJavaModule 的子類中,寫一個給 JS 返回用戶信息的方法:
@ReactMethod
public void callBackTime(String name, Callback callback) {
callback.invoke(name, getDateAndTime());//invoke 的參數是可變長參數;
在JS 端調用和接收回調如下:
<Text style={styles.welcome}
onPress={this.getCallBackTime.bind(this)}
>CallBack 獲取時間
</Text>
getCallBackTime() {
NativeModules.CommonModule.callBackTime("Allure",
(msg1, msg2) => {
console.log(msg);
ToastAndroid.show("CallBack收到消息:" + "\n" + msg1 + msg2 , ToastAndroid.SHORT)
}
);
}
2、Promise 回調
在Android 端代碼如下:
@ReactMethod
public void getBasicUserInfo(Promise promise){
WritableMap map = Arguments.createMap();
map.putString("user_id", "458");
map.putString("user_name", "jcstest");
map.putString("user_city", "北京");
map.putArray("user_privileges", getPrivilegesWritableArray());
promise.resolve(map);
}
JS端調用如下:
<TouchableHighlight onPress={_getUserInfo.bind(this)}>
<Text> Promise resolve </Text>
</TouchableHighlight>
async function _getUserInfo (){
const _this = this;
try {
ToastAndroid.show("_getUserInfo", ToastAndroid.SHORT);
const data = await NativeModules.CommonModule.getBasicUserInfo()
global.currentUser = data || {};
_this.setState({
userInfo: data,
loading: false
});
ToastAndroid.show(this.state.userInfo.user_city, ToastAndroid.SHORT);
ToastAndroid.show(this.state.userInfo.user_privileges[0], ToastAndroid.SHORT);
} catch (e) {
ToastAndroid.show(e, ToastAndroid.SHORT);
}
}
3、RCTDeviceEventEmitter 發送消息
在Android 代碼如下:
public void sendTransMission(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
if(reactContext != null){
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
JS 端接收消息代碼如下:
componentWillMount() {
this.listener = DeviceEventEmitter.addListener('EventName', function (msg) {
console.log(msg);
ToastAndroid.show("DeviceEventEmitter收到消息:" + "\n" + msg.turn + "---" + msg.key, ToastAndroid.SHORT)
});
}
componentWillUnmount(){
// 移除
this.listener.remove();
}
三、React Js 與 Native 通信三種方式的比較
- CallBack 方式 :
JS 調用,Native 返回;
CallBack 爲異步操作,返回時機不確定;
支持可變長參數,回調時參數按順序取值; - Promise 回調
JS調用,Native返回;
支持多數據類型;
每次使用需要 JS 調用一次 - RCTDeviceEventEmitter 事件
由 Native 主動向 JS 發送消息,JS 只需要監聽即可。