如何造個(gè)android Flow流式響應(yīng)的輪子
原因
在code代碼中,我們經(jīng)常碰到異步方法嵌套。比如提交文件之后在提交表單,提交數(shù)據(jù)根據(jù)是否成功然后做出其他邏輯處理。kotlin里面提出協(xié)程概念,利用語(yǔ)法糖來(lái)解決這個(gè)問(wèn)題。在javaScript里面也有async/await來(lái)使異步用起來(lái)像同步。而在java中我暫時(shí)沒(méi)有找到該特性,使得寫(xiě)起來(lái)異步嵌套感覺(jué)就是地獄,像吃了屎一樣。利用這春節(jié)幾天時(shí)間,嘗試著按自己思路去解決這個(gè)問(wèn)題,造個(gè)流式的輪子,于是寫(xiě)了Flow小框子。
想法
從生活中思考代碼,方法嵌套和水流的原理很相似,我們把每個(gè)異步當(dāng)成一個(gè)水管,水從一個(gè)個(gè)管道流過(guò),每個(gè)管道可以對(duì)水進(jìn)行加工轉(zhuǎn)換。轉(zhuǎn)換的這個(gè)過(guò)程我們當(dāng)成一個(gè)事件Event。在包裝事件中,我們可以對(duì)它進(jìn)行線(xiàn)程轉(zhuǎn)換,事件轉(zhuǎn)換,合并拆分等一系列轉(zhuǎn)換。如果碰到異常,則直接終止這個(gè)流。
功能
簡(jiǎn)單使用
通過(guò)Flow 靜態(tài)create方法創(chuàng)建一個(gè)流,then串聯(lián)下個(gè)流,如果不需要返回Void泛型。Event有兩個(gè)泛型P、R,第一個(gè)是前個(gè)流Flow的返回值類(lèi)型,第二個(gè)是當(dāng)前流Flow返回類(lèi)型。await exec方法是結(jié)束當(dāng)前事件流,并將結(jié)果代入下個(gè)流。
打印兩句話(huà)
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é)果。如果遇到異常,可以通過(guò)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();
切換線(xiàn)程
使用flow on方法可以切換線(xiàn)程,on傳遞一個(gè)Converter參數(shù),代表下個(gè)流切換。如果兩個(gè)Converter參數(shù),代表當(dāng)前流和下個(gè)流都切換線(xiàn)程。當(dāng)然你也可以實(shí)現(xiàn)Converter接口來(lái)實(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();
生命周期解綁
通過(guò)flow watch方法。被觀察者必須實(shí)現(xiàn)ILifeObservable接口。
Flow.create((FirstEvent<Integer>) (flow, await) ->await.exec(0)) .watch(this).start();
總結(jié)
框子也里面提供了一些簡(jiǎn)化的類(lèi),也可以和項(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)化開(kāi)發(fā),提供了不少轉(zhuǎn)換動(dòng)畫(huà)組件,這類(lèi)組件通常命名為 xxTransition。本篇要介紹的就是 SlideTransition,并用它實(shí)現(xiàn)圖片滑動(dòng)切換效果,感興趣的可以了解一下2022-04-04
Android中使用TagFlowLayout制作動(dòng)態(tài)添加刪除標(biāo)簽
這篇文章主要介紹了Android中使用TagFlowLayout制作動(dòng)態(tài)添加刪除標(biāo)簽的步驟詳解,需要的朋友參考下吧2017-07-07
Qt6.5.3?Android環(huán)境配置的實(shí)現(xiàn)
本文主要介紹了Qt6.5.3?Android環(huán)境配置的實(shí)現(xiàn),文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
Android自定義加載loading view動(dòng)畫(huà)組件
這篇文章主要為大家詳細(xì)介紹了Android自定義加載loading view動(dòng)畫(huà)組件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
Android 使用地圖時(shí)的權(quán)限請(qǐng)求方法
今天小編就為大家分享一篇Android 使用地圖時(shí)的權(quán)限請(qǐng)求方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
Android開(kāi)發(fā)自定義短信驗(yàn)證碼實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家介紹了Android開(kāi)發(fā)自定義短信驗(yàn)證碼實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Android音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)案例
我們平時(shí)長(zhǎng)時(shí)間打代碼的時(shí)候肯定會(huì)感到疲憊和乏味,這個(gè)時(shí)候一邊播放自己喜歡的音樂(lè),一邊繼續(xù)打代碼,心情自然也愉快很多。音樂(lè)帶給人的聽(tīng)覺(jué)享受是無(wú)可比擬的,動(dòng)聽(tīng)的音樂(lè)可以愉悅?cè)说纳硇模屓烁臃e極地去熱愛(ài)生活,這篇文章主要介紹了Android音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)案例2022-12-12
TextView使用SpannableString設(shè)置復(fù)合文本 SpannableString實(shí)現(xiàn)TextView的鏈接
這篇文章主要為大家詳細(xì)介紹了如何利用SpannableString實(shí)現(xiàn)TextView的鏈接效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08

