造個android Flow流式響應的輪子

點我啊,代碼在這裏

緣由

在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就幾乎同樣了。後續根據實際需求再作調整,試驗中。

相關文章
相關標籤/搜索