在code代碼中,咱們常常碰到異步方法嵌套。好比提交文件以後在提交表單,提交數據根據是否成功而後作出其餘邏輯處理。kotlin
裏面提出協程概念,利用語法糖來解決這個問題。在javaScript
裏面也有async/await
來使異步用起來像同步。而在java
中我暫時沒有找到該特性,使得寫起來異步嵌套感受就是地獄,像吃了屎同樣。利用這春節幾天時間,嘗試着按本身思路去解決這個問題,造個流式的輪子,因而寫了Flow
小框子。java
從生活中思考代碼,方法嵌套和水流的原理很類似,咱們把每一個異步當成一個水管,水從一個個管道流過,每一個管道能夠對水進行加工轉換。轉換的這個過程咱們當成一個事件Event
。在包裝事件中,咱們能夠對它進行線程轉換,事件轉換,合併拆分等一系列轉換。若是碰到異常,則直接終止這個流。git
經過Flow
靜態create
方法建立一個流,then
串聯下個流,若是不須要返回Void
泛型。Event
有兩個泛型P、R
,第一個是前個流Flow
的返回值類型,第二個是當前流Flow
返回類型。await exec
方法是結束當前事件流,並將結果代入下個流。github
打印兩句話bash
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
簡化以後網絡
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();
複製代碼
兩數相加框架
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
方法返回是當前流的結果,每一個flow
後面使用resultThen
均可以獲取流的結果。若是遇到異常,能夠經過flow throwException
方法拋出,能夠在flow
後面catchThen
馬上處理,也能夠在最後flow
catchThen
處理。finallyThen
是事件流結束一個通知。異步
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
傳遞一個Converter
參數,表明下個流切換。若是兩個Converter
參數,表明當前流和下個流都切換線程。固然你也能夠實現Converter
接口來實現其餘功能。async
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
結果轉換成多個流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();
複製代碼
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();
複製代碼
根據條件判斷從新發起Flow
流(返回參數能夠不同)ide
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();
複製代碼
根據條件判斷執行Flow
流,能夠合併到一塊兒。(返回參數必須一致)ui
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
方法。被觀察者必須實現ILifeObservable
接口。
Flow.create((FirstEvent<Integer>) (flow, await) ->await.exec(0))
.watch(this).start();
複製代碼
框子也裏面提供了一些簡化的類,也能夠和項目網絡請求框架抽象本身的Event
,這樣和js
的網絡的then
就幾乎同樣了。後續根據實際需求再作調整,試驗中。