AndroidFlux-異步請求和網絡

jopen 8年前發布 | 7K 次閱讀 Android開發 移動開發

在移動開發中,異步網絡操作必不可少,本篇著重介紹在Flux模式中如何處理異步操作的問題,并深入一些細節,比如如何在異步操作時顯示異步狀態。另外,網絡操作僅僅是異步操作的一種,最后擴展ActionCreator的語義來處理更多的業務邏輯。

如何做網絡操作


如圖所示,在FluxApp中,網絡操作是在ActionCreator部分執行的。


network

之所以這樣是因為,Flux的整體架構是一個單向數據流,數據從Action開始最終經過Dispatcher、Store流向View,在這個過程中ActionCreator屬于數據的預處理和準備階段。所以像網絡請求、文件處理、數據預處理等等都應該在這里完成,最后產出一個結果通過Action啟動整個數據流。

一個典型的異步網絡請求代碼是這樣的:

public void usrlogin(String account, String pw) {
    // tell store to show loading-dialog
    dispatcher.dispatch(new Action(LoginAction.ACTION_LOGIN_START));
    // start Rest API
    RestAPI.login(account, pw).enqueue(
        new RestCallback<JsonUser>() {
            @Override
            public void onSucceed(JsonUser juser) {
                // tell store that login-req success
                dispatcher.dispatch(new Action(LoginAction.ACTION_LOGIN_SUCCESS, juser));
            }

            @Override
            public void onError(String message) {
                // tell store that login-req fail
                dispatcher.dispatch(new Action(LoginAction.ACTION_LOGIN_FAIL, message));
            }
        }
    );
}

這里需要注意一個細節,在發起異步操作之后,我們需要顯示一個“正在加載…”對話框或者顯示一個發送狀態。傳統的做法可能是這樣的,發起網絡請求,提供一個回調接口,在回調接口中,隱藏“正在加載”對話框。典型的代碼如下:

public void usrlogin(String account, String pw) {
    // show loading-dialog
    showLoadingDialog();
    // start RestAPI
    RestAPI.login(account, pw).enqueue(
        new RestCallback<JsonUser>() {
            @Override
            public void onSucceed(JsonUser juser) {
                hideLoadingDialog();
                // do something...
            }

            @Override
            public void onError(String message) {
                hideLoadingDialog();
                // handle error
            }
        }
    );
}

在Flux中,要始終注意數據是單向流動的,所以要抵制住這種誘惑。Flux的處理方式是在數據開始加載的時候,發送Action給Store,讓Store來處理當前的UI狀態,比如顯示一個“正在加載…”的對話框。在網絡請求成功/失敗之后,再發送新的Action給Store處理請求結果。(額外的好處是,避免了常見的由于回調接口造成的內存泄漏問題)

樂觀與悲觀

這個問題經常出現在如下場景中,比如微信的點贊功能,由于網絡延遲,我們在點贊之后并不是立刻拿到點贊是否成功的結果的,處理方式有兩種:

  1. 樂觀的處理方式 點贊之后立刻顯示點贊為成功狀態,如果網絡操作失敗則撤銷點贊成功的狀態。
  2. 悲觀的處理方式 點贊之后先做網絡請求,根據請求結果,再顯示點贊狀態

兩者處理方式各有利弊,前者的問題在于如果網絡請求失敗,撤銷點贊是一種很奇怪的現象。后者的問題在于,雖然看上去UI邏輯都是正確的,但是用戶體驗會很糟,在網絡比較差的情況下,即使點贊這種“廉價”的操作也會等上幾秒。(微信和FB都是采用樂觀的方式,這種處理方式默認大部分情況下網絡操作都會成功)

擴展的ActionCreator語義

就像剛開始分析的那樣,ActionCreator負責的是數據的準備和預處理,而網絡請求只是個例。所以,實際上ActionCreator給我們提供了一個處理一般業務邏輯的地方。這些業務和Flux數據流和UI邏輯沒有關系,更多的是App的業務邏輯,比如在給一個手機號發送驗證碼之前(這也是一個網絡請求,但是需要手機號作為payload),需要驗證用戶輸入的手機號是否合法。再比如,做本地圖片選擇器的時候,需要調用圖片庫獲取圖片數據,這些類似操作,都是App的業務邏輯負責準備數據的事情,并不是App的UI邏輯,所以應該放在ActionCreator來做(Store對處理這類邏輯有很強的誘惑力,在Store中處理也是可以的,但是要記的不要在Store里面直接更新Store狀態,要通過Action來更新)。

在Flux架構中,ActionCreator雖然和Flux數據流關系不大,但對于App來說,實際上是非常重要的一部分。它是對UserCase的抽象,每一個UserCase都可以抽象成ActionCreator的一個方法。

網絡操作-讀與寫

Flux的作者曾經專門回答過ActionCreator和網絡讀寫的問題,這對于代碼強迫癥患者頗有幫助:

One thing I also wanted to add is that I usually view ActionCreators (what were previously called actions) as something that is used for writes to the server. For example, the user added a new message by clicking the Send button, so the responsible view calls into ActionCreator.

On the other hand, if a store needs to fetch data from the server (if a scroll load in the view triggers a request for data we currently don't have), then that doesn't have to use an ActionCreator. Instead, the store can directly hit an endpoint to load its data, and then direct the response through the dispatcher.

One way to think about this distinction is that an Action, initiated from from the view, could change multiple stores (i.e. sending a message updates both the messages store and the thread store). Thus, the error handler would need to update globally that the optimistic action needs to roll back. So the role of an ActionCreator is to (1) format the Action in a standard way, rather than having different views do this, and (2) coordinate optimistic actions and the server response (whether a confirm or an error). On the other hand, data fetching from the store doesn't need either of those, and can avoid the extra layer of ActionCreator completely.

這段話主要是說一般網絡操作在ActionCreator中來做,網絡操作在Store中來做。理由是,ActionCreator在做網絡請求時的職責,1). 規范化Action的創建 2). 協調樂觀的網絡操作,處理請求成功或者失敗的情況的。但是在網絡讀操作的時候不需要這些操作,所以也不需要放在ActionCreator中完成。

這是AndroidFlux站點上介紹異步請求和網絡相關的文檔。更多閱讀:

  1. 為Android選擇一個合適的架構
  2. AndroidFlux項目一覽-Flux架構的Android移植
  3. AndroidFlux入門-用Flux構建Android平臺的HelloWorld應用
  4. AndroidFlux-Store和數據存儲

來自: http://www.jianshu.com/p/3baddb51f5a4

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!