如何造個(gè)android Flow流式響應(yīng)的輪子
原因
在code代碼中,我們經(jīng)常碰到異步方法嵌套。比如提交文件之后在提交表單,提交數(shù)據(jù)根據(jù)是否成功然后做出其他邏輯處理。kotlin里面提出協(xié)程概念,利用語(yǔ)法糖來解決這個(gè)問題。在javaScript里面也有async/await來使異步用起來像同步。而在java中我暫時(shí)沒有找到該特性,使得寫起來異步嵌套感覺就是地獄,像吃了屎一樣。利用這春節(jié)幾天時(shí)間,嘗試著按自己思路去解決這個(gè)問題,造個(gè)流式的輪子,于是寫了Flow小框子。
想法
從生活中思考代碼,方法嵌套和水流的原理很相似,我們把每個(gè)異步當(dāng)成一個(gè)水管,水從一個(gè)個(gè)管道流過,每個(gè)管道可以對(duì)水進(jìn)行加工轉(zhuǎn)換。轉(zhuǎn)換的這個(gè)過程我們當(dāng)成一個(gè)事件Event。在包裝事件中,我們可以對(duì)它進(jìn)行線程轉(zhuǎn)換,事件轉(zhuǎn)換,合并拆分等一系列轉(zhuǎn)換。如果碰到異常,則直接終止這個(gè)流。
功能
簡(jiǎn)單使用
通過Flow 靜態(tài)create方法創(chuàng)建一個(gè)流,then串聯(lián)下個(gè)流,如果不需要返回Void泛型。Event有兩個(gè)泛型P、R,第一個(gè)是前個(gè)流Flow的返回值類型,第二個(gè)是當(dāng)前流Flow返回類型。await exec方法是結(jié)束當(dāng)前事件流,并將結(jié)果代入下個(gè)流。
打印兩句話
Flow.create(new Event<Void,Void>() { @Override public void run(Flow flow, Void aVoid, Await<Void> await) { System.out.println("this is first flow"); await.exec(null); } }).then(new Event<Void, Void>() { @Override public void run(Flow flow, Void aVoid, Await<Void> await) { System.out.println("this is two flow"); await.exec(null); } }).start();
Lambda簡(jiǎn)化之后
Flow.create((NoneEvent) (flow, await) -> { System.out.println("this is first flow"); await.exec(); }).then((NoneEvent) (flow, await) -> { System.out.println("this is two flow"); await.exec(); }).start();
兩數(shù)相加
Flow.create((FirstEvent<Integer>) (flow, await) -> await.exec(3)) .then((Event<Integer, Integer>) (flow, integer, await) -> await.exec(integer + 5)) .resultThen((flow, result) -> System.out.println("total is"+result)) .start();
resultThen方法返回是當(dāng)前流的結(jié)果,每個(gè)flow后面使用resultThen都可以獲取流的結(jié)果。如果遇到異常,可以通過flow throwException方法拋出,可以在flow后面catchThen立刻處理,也可以在最后flow catchThen處理。finallyThen是事件流結(jié)束一個(gè)通知。
Flow.create((FirstEvent<Integer>) (flow, await) -> await.exec(0)) .then((Event<Integer, Integer>) (flow, perVal, await) ->{ if(perVal == 0){ flow.throwException("Dividend cannot be 0!"); }else{ await.exec(perVal/5); } }) .resultThen((flow, result) -> System.out.println("total is"+result)) .catchThen((flow, e) -> System.out.println(e.getMessage())) .finallyThen((flow, await) -> System.out.println("this is flow end")).start();
切換線程
使用flow on方法可以切換線程,on傳遞一個(gè)Converter參數(shù),代表下個(gè)流切換。如果兩個(gè)Converter參數(shù),代表當(dāng)前流和下個(gè)流都切換線程。當(dāng)然你也可以實(shí)現(xiàn)Converter接口來實(shí)現(xiàn)其他功能。
Flow.create((FirstEvent<Integer>) (flow, await) -> await.exec(0)) .on(AndroidMain.get(),SingleThread.get()) .then((Event<Integer, Integer>) (flow, perVal, await) ->{ if(perVal == 0){ flow.throwException("Dividend cannot be 0!"); }else{ await.exec(perVal/5); } }) .on(AndroidMain.get()) .resultThen((flow, result) -> System.out.println("total is"+result)) .on(AndroidMain.get()) .catchThen((flow, e) -> System.out.println(e.getMessage())) .on(SingleThread.get()) .finallyThen((flow, await) -> System.out.println("this is flow end")).start();
Collection結(jié)果轉(zhuǎn)換成多個(gè)流
Flow.each((FirstEvent<List<String>>) (flow, await) -> { ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); await.exec(list); }).then((LastEvent<String>) (flow, s, await) -> { System.out.println("this is"+s); }).start();
多個(gè)流結(jié)果轉(zhuǎn)換成一個(gè)流
Flow.merge((flow, await) -> await.exec(1), (flow, await) -> await.exec(2), (flow, await) -> await.exec(2)).resultThen((flow, result) -> System.out.println"result"+result)).start();
條件選擇
根據(jù)條件判斷重新發(fā)起Flow流(返回參數(shù)可以不一樣)
Flow.create((NoneEvent) (flow,await) ->{ System.out.println("start"); await.exec(); }) .on(SingleThread.get()) .conditionThen((VoidCondition) () -> false, Flow.create((NoneEvent) (flow,await) -> { System.out.println("this is true"); await.exec(); }), Flow.create((NoneEvent) (flow,await) -> { System.out.println("this is false"); await.exec(); })).start();
根據(jù)條件判斷執(zhí)行Flow流,可以合并到一起。(返回參數(shù)必須一致)
Flow.condition2(() -> isGo, (FirstEvent<Integer>) (flow, await) -> { System.out.println("this is true"); await.exec(1); }, (flow, await) -> { System.out.println("this is false"); await.exec(0); }).resultThen((flow, result) -> System.out.println("result"+result)) .watch(this).start();
生命周期解綁
通過flow watch方法。被觀察者必須實(shí)現(xiàn)ILifeObservable接口。
Flow.create((FirstEvent<Integer>) (flow, await) ->await.exec(0)) .watch(this).start();
總結(jié)
框子也里面提供了一些簡(jiǎn)化的類,也可以和項(xiàng)目網(wǎng)絡(luò)請(qǐng)求框架抽象自己的Event,這樣和js的網(wǎng)絡(luò)的then就幾乎一樣了。后續(xù)根據(jù)實(shí)際需求再做調(diào)整,試驗(yàn)中。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Flutter實(shí)現(xiàn)圖片滑動(dòng)切換效果
Flutter 為了簡(jiǎn)化開發(fā),提供了不少轉(zhuǎn)換動(dòng)畫組件,這類組件通常命名為 xxTransition。本篇要介紹的就是 SlideTransition,并用它實(shí)現(xiàn)圖片滑動(dòng)切換效果,感興趣的可以了解一下2022-04-04Android中使用TagFlowLayout制作動(dòng)態(tài)添加刪除標(biāo)簽
這篇文章主要介紹了Android中使用TagFlowLayout制作動(dòng)態(tài)添加刪除標(biāo)簽的步驟詳解,需要的朋友參考下吧2017-07-07Qt6.5.3?Android環(huán)境配置的實(shí)現(xiàn)
本文主要介紹了Qt6.5.3?Android環(huán)境配置的實(shí)現(xiàn),文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01Android自定義加載loading view動(dòng)畫組件
這篇文章主要為大家詳細(xì)介紹了Android自定義加載loading view動(dòng)畫組件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08Android 使用地圖時(shí)的權(quán)限請(qǐng)求方法
今天小編就為大家分享一篇Android 使用地圖時(shí)的權(quán)限請(qǐng)求方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07Android開發(fā)自定義短信驗(yàn)證碼實(shí)現(xiàn)過程詳解
這篇文章主要為大家介紹了Android開發(fā)自定義短信驗(yàn)證碼實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Android音樂播放器簡(jiǎn)單實(shí)現(xiàn)案例
我們平時(shí)長(zhǎng)時(shí)間打代碼的時(shí)候肯定會(huì)感到疲憊和乏味,這個(gè)時(shí)候一邊播放自己喜歡的音樂,一邊繼續(xù)打代碼,心情自然也愉快很多。音樂帶給人的聽覺享受是無可比擬的,動(dòng)聽的音樂可以愉悅?cè)说纳硇模屓烁臃e極地去熱愛生活,這篇文章主要介紹了Android音樂播放器簡(jiǎn)單實(shí)現(xiàn)案例2022-12-12TextView使用SpannableString設(shè)置復(fù)合文本 SpannableString實(shí)現(xiàn)TextView的鏈接
這篇文章主要為大家詳細(xì)介紹了如何利用SpannableString實(shí)現(xiàn)TextView的鏈接效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08