Android React Native原生模塊與JS模塊通信的方法總結(jié)
Android React Native原生模塊與JS模塊通信的方法總結(jié)
前言:
在做React Native開發(fā)的時(shí)候避免不了的需要原生模塊和JS之間進(jìn)行數(shù)據(jù)傳遞,這篇文章將向大家分享原生模塊向JS傳遞數(shù)據(jù)的幾種方式。
方式一:通過Callbacks的方式
說(shuō)起Callbacks大家都不陌生,它是最常用的設(shè)計(jì)模式之一。無(wú)論是Java,Object-c,C#,還是JavaScript等都會(huì)看到Callbacks的身影。
原生模塊支持Callbacks類型的參數(shù),該Callbacks對(duì)應(yīng)JS中的function。
在原生模塊中:
public class RNTestModule extends ReactContextBaseJavaModule{
public RNTestModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "RNTest";
}
@ReactMethod
public void measureLayout(
int tag,
int ancestorTag,
Callback errorCallback,
Callback successCallback) {
try {
measureLayout(tag, ancestorTag, mMeasureBuffer);
map.putDouble("relativeX",1);
map.putDouble("relativeY", 1);
map.putDouble("width", 2);
map.putDouble("height",3);
successCallback.invoke(relativeX, relativeY, width, height);
} catch (IllegalViewOperationException e) {
errorCallback.invoke(e.getMessage());
}
}
在上述代碼中,measureLayout方法的參數(shù)中后兩個(gè)就是Callbacks,當(dāng)原生模塊處理成功時(shí)通過successCallback回調(diào)來(lái)告知JS處理成功的結(jié)果,當(dāng)原生模塊發(fā)生異常時(shí),則通過errorCallback回調(diào)來(lái)JS處理異常。
在JS模塊中:
RNTest.measureLayout(
100,
100,
(msg) => {
console.log(msg);
},
(x, y, width, height) => {
console.log(x + ':' + y + ':' + width + ':' + height);
}
);
上述代碼,是在JS模塊中調(diào)用原生模塊的方法measureLayout,同時(shí)向它傳遞了四個(gè)參數(shù),后兩個(gè)是function類型的參數(shù)用于接收原生模塊的處理結(jié)果。
通過上述的方式,JS調(diào)用原生模塊的measureLayout方法,原生模塊則通過errorCallback與successCallbackCallbacks來(lái)將處理結(jié)果傳遞到JS。
這種“You call me,I will callback”,的方式小伙伴們都看懂了吧。
方式二:通過Promises的方式
Promises是ES6的一個(gè)新的特性,在React Native中你會(huì)看到Promises的大量使用。
原生模塊也是支持Promises的,這對(duì)喜歡使用Promises的小伙伴則是一個(gè)很好的消息。
在原生模塊中:
public class RNTestModule extends ReactContextBaseJavaModule{
public RNTestModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "RNTest";
}
@ReactMethod
public void measureLayout(
int tag,
int ancestorTag,
Promise promise) {
try {
WritableMap map = Arguments.createMap();
map.putDouble("relativeX",1);
map.putDouble("relativeY", 1);
map.putDouble("width", 2);
map.putDouble("height",3);
promise.resolve(map);
} catch (IllegalViewOperationException e) {
promise.reject(e);
}
}
}
上述代碼中,measureLayout方法接收的最后一個(gè)為Promise,當(dāng)相應(yīng)的處理結(jié)果出來(lái)之后原生模塊通過調(diào)用Promise的相應(yīng)方法來(lái)向JS模塊傳遞處理成功,或處理失敗的數(shù)據(jù)。
提示:在原生模塊中Promise類型的參數(shù)要放在最后一位,這樣JS調(diào)用的時(shí)候才能返回一個(gè)Promise。
在JS模塊中:
async test() {
try {
var {
relativeX,
relativeY,
width,
height,
} = await RNTest.measureLayout(100, 100);
console.log(relativeX + ':' + relativeY + ':' + width + ':' + height);
} catch (e) {
console.error(e);
}
}
在上述代碼中,通過ES7的新特性async/await來(lái)修飾了test方法,來(lái)以同步方式調(diào)用原生模塊的measureLayout方法,如果原生模塊處理成功,
那么JS中relativeX,relativeY,width,height會(huì)獲得相應(yīng)的值,如果原生模塊處理失敗,則會(huì)拋出異常。
如果,不希望以同步的形式調(diào)用,可以這樣寫:
test2(){
RNTest.measureLayout(100,100).then(e=>{
console.log(e.relativeX + ':' + e.relativeY + ':' + e.width + ':' + e.height);
this.setState({
relativeX:e.relativeX,
relativeY:e.relativeY,
width:e.width,
height:e.height,
})
}).catch(error=>{
console.log(error);
});
}
以上就是通過Promises的方式向JS傳遞數(shù)據(jù)的方式,小伙伴們看懂了嗎。
上述兩種方式,通過Callbacks的方式與通過Promises的方式,都可以向JS模塊傳遞數(shù)據(jù),但都是只能傳遞一次。
如果,你需要多次向JS模塊傳遞數(shù)據(jù)(如:按鍵事件)上述方式還是不夠好,下面就像大家分享可以多次傳遞數(shù)據(jù)的方式。
方式三:通過發(fā)送事件的方式
原生模塊支持另外一種向JS模塊傳遞數(shù)據(jù)的方式,通過發(fā)送事件的方式。
原生模塊,可以向JS傳遞事件而不要而不需要直接的調(diào)用,就像Android中的廣播,iOS中的通知中心。
下面就向大家演示通過RCTDeviceEventEmitter,來(lái)向JS傳遞事件。
在原生模塊中:
@Override
public void onHandleResult(String barcodeData) {
WritableMap params = Arguments.createMap();
params.putString("result", barcodeData);
sendEvent(getReactApplicationContext(), "onScanningResult", params);
}
private void sendEvent(ReactContext reactContext,String eventName, @Nullable WritableMap params) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
上述代碼向JS模塊發(fā)送了一個(gè)名為“onScanningResult”的事件,并攜帶了“params”作為參數(shù)。
在JS模塊中:
下面是在JS代碼中進(jìn)行監(jiān)聽原生模塊發(fā)出的名為“onScanningResult”的事件。
componentDidMount() {
//注冊(cè)掃描監(jiān)聽
DeviceEventEmitter.addListener('onScanningResult',this.onScanningResult);
}
onScanningResult = (e)=> {
this.setState({
scanningResult: e.result,
});
// DeviceEventEmitter.removeListener('onScanningResult',this.onScanningResult);//移除掃描監(jiān)聽
}
在JS中通過DeviceEventEmitter注冊(cè)監(jiān)聽了名為“onScanningResult”的事件,當(dāng)原生模塊發(fā)出名為“onScanningResult”的事件后,綁定在該事件上的onScanningResult = (e)會(huì)被回調(diào)。
然后通過e.result就可獲得事件所攜帶的數(shù)據(jù)。
心得:如果在JS中有多處注冊(cè)了onScanningResult事件,那么當(dāng)原生模塊發(fā)出事件后,這幾個(gè)地方會(huì)同時(shí)收到該事件。不過大家也可以通過DeviceEventEmitter.removeListener('onScanningResult',this.onScanningResult) 來(lái)移除對(duì)名為“onScanningResult”事件的監(jiān)聽。
另外,JS模塊也支持通過Subscribable mixin,也注冊(cè)監(jiān)聽事件,因?yàn)镋S6已經(jīng)不再推薦使用mixin,所以在這里也就不向大家介紹了。
三種方式的優(yōu)缺點(diǎn)
| 方式 | 缺點(diǎn) | 優(yōu)點(diǎn) |
|---|---|---|
| 通過Callbacks的方式 | 只能傳遞一次 | 傳遞可控,JS模塊調(diào)用一次,原生模塊傳遞一次 |
| 通過Promises的方式 | 只能傳遞一次 | 傳遞可控,JS模塊調(diào)用一次,原生模塊傳遞一次 |
| 通過發(fā)送事件的方式 | 原生模塊主動(dòng)傳遞,JS模塊被動(dòng)接收 | 可多次傳遞 |
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android下使用TCPDUMP實(shí)現(xiàn)數(shù)據(jù)抓包教程
這篇文章主要介紹了Android下使用TCPDUMP實(shí)現(xiàn)數(shù)據(jù)抓包教程,本文講解使用抓包工具tcpdump抓取數(shù)據(jù),然后使用Wireshark來(lái)分析數(shù)據(jù),需要的朋友可以參考下2015-02-02
android 圖片操作(縮放移動(dòng)) 實(shí)例代碼
android 圖片操作(縮放移動(dòng)) 實(shí)例代碼,需要的朋友可以參考一下2013-06-06
Android開發(fā)實(shí)現(xiàn)SubMenu選項(xiàng)菜單和子菜單示例
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)SubMenu選項(xiàng)菜單和子菜單,結(jié)合實(shí)例形式分析了Android開發(fā)中SubMenu選項(xiàng)菜單和子菜單的功能、配置、布局等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03
Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法
看過很多?supervisorScope {}?文檔的使用,我照抄一摸一樣的代碼,運(yùn)行就崩潰,最后找到了解決方法,應(yīng)該是kotlin版本更新做過改動(dòng),當(dāng)前我使用的是?androidx.core:core-ktx:1.9.0,本文給大家介紹Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法,感興趣的朋友一起看看吧2024-01-01
Android編程自定義菜單實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Android編程自定義菜單實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Android自定義菜單的布局、動(dòng)畫及功能相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下2017-02-02
Android Kotlin的使用及簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android Kotlin的使用及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05
android基礎(chǔ)教程之夜間模式實(shí)現(xiàn)示例
這篇文章主要介紹了android的夜間模式實(shí)現(xiàn)示例,需要的朋友可以參考下2014-02-02
Android實(shí)現(xiàn)Unity3D下RTMP推送的示例
像Unity3D下的RTMP或RTSP播放器一樣,好多開發(fā)者苦于在Unity環(huán)境下,如何高效率低延遲的把數(shù)據(jù)采集并編碼實(shí)時(shí)推送到流媒體服務(wù)器,實(shí)現(xiàn)Unity場(chǎng)景下的低延遲推拉流方案。本文介紹幾種RTMP推送的方案2021-06-06

