Android React Native原生模塊與JS模塊通信的方法總結(jié)
Android React Native原生模塊與JS模塊通信的方法總結(jié)
前言:
在做React Native開發(fā)的時候避免不了的需要原生模塊和JS之間進(jìn)行數(shù)據(jù)傳遞,這篇文章將向大家分享原生模塊向JS傳遞數(shù)據(jù)的幾種方式。
方式一:通過Callbacks的方式
說起Callbacks大家都不陌生,它是最常用的設(shè)計模式之一。無論是Java,Object-c,C#,還是JavaScript等都會看到Callbacks的身影。
原生模塊支持Callbacks類型的參數(shù),該Callbacks對應(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ù)中后兩個就是Callbacks,當(dāng)原生模塊處理成功時通過successCallback回調(diào)來告知JS處理成功的結(jié)果,當(dāng)原生模塊發(fā)生異常時,則通過errorCallback回調(diào)來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ù),后兩個是function類型的參數(shù)用于接收原生模塊的處理結(jié)果。
通過上述的方式,JS調(diào)用原生模塊的measureLayout方法,原生模塊則通過errorCallback與successCallbackCallbacks來將處理結(jié)果傳遞到JS。
這種“You call me,I will callback”,的方式小伙伴們都看懂了吧。
方式二:通過Promises的方式
Promises是ES6的一個新的特性,在React Native中你會看到Promises的大量使用。
原生模塊也是支持Promises的,這對喜歡使用Promises的小伙伴則是一個很好的消息。
在原生模塊中:
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方法接收的最后一個為Promise,當(dāng)相應(yīng)的處理結(jié)果出來之后原生模塊通過調(diào)用Promise的相應(yīng)方法來向JS模塊傳遞處理成功,或處理失敗的數(shù)據(jù)。
提示:在原生模塊中Promise類型的參數(shù)要放在最后一位,這樣JS調(diào)用的時候才能返回一個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來修飾了test方法,來以同步方式調(diào)用原生模塊的measureLayout方法,如果原生模塊處理成功,
那么JS中relativeX,relativeY,width,height會獲得相應(yīng)的值,如果原生模塊處理失敗,則會拋出異常。
如果,不希望以同步的形式調(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,來向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ā)送了一個名為“onScanningResult”的事件,并攜帶了“params”作為參數(shù)。
在JS模塊中:
下面是在JS代碼中進(jìn)行監(jiān)聽原生模塊發(fā)出的名為“onScanningResult”的事件。
componentDidMount() { //注冊掃描監(jiān)聽 DeviceEventEmitter.addListener('onScanningResult',this.onScanningResult); } onScanningResult = (e)=> { this.setState({ scanningResult: e.result, }); // DeviceEventEmitter.removeListener('onScanningResult',this.onScanningResult);//移除掃描監(jiān)聽 }
在JS中通過DeviceEventEmitter注冊監(jiān)聽了名為“onScanningResult”的事件,當(dāng)原生模塊發(fā)出名為“onScanningResult”的事件后,綁定在該事件上的onScanningResult = (e)會被回調(diào)。
然后通過e.result就可獲得事件所攜帶的數(shù)據(jù)。
心得:如果在JS中有多處注冊了onScanningResult事件,那么當(dāng)原生模塊發(fā)出事件后,這幾個地方會同時收到該事件。不過大家也可以通過DeviceEventEmitter.removeListener('onScanningResult',this.onScanningResult) 來移除對名為“onScanningResult”事件的監(jiān)聽。
另外,JS模塊也支持通過Subscribable mixin,也注冊監(jiān)聽事件,因為ES6已經(jīng)不再推薦使用mixin,所以在這里也就不向大家介紹了。
三種方式的優(yōu)缺點
方式 | 缺點 | 優(yōu)點 |
---|---|---|
通過Callbacks的方式 | 只能傳遞一次 | 傳遞可控,JS模塊調(diào)用一次,原生模塊傳遞一次 |
通過Promises的方式 | 只能傳遞一次 | 傳遞可控,JS模塊調(diào)用一次,原生模塊傳遞一次 |
通過發(fā)送事件的方式 | 原生模塊主動傳遞,JS模塊被動接收 | 可多次傳遞 |
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Android自定義PopupWindow仿點擊彈出分享功能
這篇文章主要為大家詳細(xì)介紹了Android自定義PopupWindow仿點擊彈出分享功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android開發(fā)中使用顏色矩陣改變圖片顏色,透明度及亮度的方法
這篇文章主要介紹了Android開發(fā)中使用顏色矩陣改變圖片顏色,透明度及亮度的方法,涉及Android針對圖片的讀取、運算、設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10Flutter進(jìn)階之實現(xiàn)動畫效果(七)
這篇文章主要為大家詳細(xì)介紹了Flutter進(jìn)階之實現(xiàn)動畫效果的第七篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08Android 7.0系統(tǒng)webview 顯示https頁面空白處理方法
今天小編就為大家分享一篇Android 7.0系統(tǒng)webview 顯示https頁面空白處理方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07Android Studio應(yīng)用開發(fā)集成百度語音合成使用方法實例講解
這篇文章主要介紹了Android Studio應(yīng)用開發(fā)集成百度語音合成使用方法實例講解的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-11-11Android中Notification用法實例總結(jié)
這篇文章主要介紹了Android中Notification用法,以實例形式較為詳細(xì)的分析并總結(jié)了Notification的功能與使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10Android ImageView Src 和Background 區(qū)別
這篇文章主要介紹了Android ImageView Src 和Background 區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-09-09