RxFluxArchitecture框架介紹1-基本功能實現

coolfire2015發表於2019-05-13

架構圖

架構圖.jpg

框架介紹

  • 該框架使用 Flux 架構,資料朝單一方向流動。
  • 上一級不需要持有下一級物件,不需要知道下一級如何實現響應。
  • ActionCreator 類似 MVP 架構中的 Presenter,只是其中不持有 View 物件,無需操作結束回撥 View 的響應方法。
  • Store 繼承自androidx.lifecycle.ViewModel,可以通過androidx.lifecycle.LiveData<T>實現 MVVM 架構。
  • Store 自動關聯 View 生命週期,維持裝置橫豎屏切換時資料。
  • View,Store 自動註冊訂閱、解除訂閱。
  • 使用 Dagger.Android 實現 View (Activity/Fragment)的依賴注入。
  • 使用實現 Tag 功能的 EventBus 實現資料匯流排功能。

功能實現1:操作響應RxActionRxChange,以登入功能為例

  1. View

LoginFragment點選登入按鈕,呼叫LoginActionCreator中的方法login(String,String)

    @OnClick(R2.id.btn_login)
    public void login() {
        mActionCreator.login(username, password);
    }
複製程式碼
  1. ActionCreator

LoginActionCreator的方法login(String,String)postHttpAction(RxAction, Observable<T>)方法會呼叫WanApi介面方法進行登入操作,登入完成後傳送封裝介面返回結果的RxAction(包含TagLoginAction.LOGIN)。

    @Override
    public void login(String username, String password) {
        RxAction rxAction = newRxAction(LoginAction.LOGIN);
        postHttpAction(rxAction, mWanApi.login(username, password).flatMap(verifyResponse()));
    }
複製程式碼
  1. Store

LoginStore中接收Tag為LoginAction.LOGIN,資料型別為RxAction的通知。取出RxAction中封裝的介面返回資料,然後使用方法postChange(RxChange)通知 View 進行 UI 響應操作。

    @Subscribe(tags = {LoginAction.LOGIN})
    public void onLogin(RxAction rxAction) {
        mUser = rxAction.getResponse();
        postChange(RxChange.newInstance(rxAction.getTag()));
    }
複製程式碼
  1. View

LoginActivity中接收Tag為LoginAction.LOGIN,資料型別為RxChange的通知,跳轉其他頁面。

    @Subscribe(tags = {LoginAction.LOGIN}, sticky = true)
    public void onLogin(RxChange rxChange) {
        startActivity(new Intent(this, ArticleActivity.class));
        finish();
    }
複製程式碼

功能實現2:進度通知RxLoading

  1. ActionCreator

LoginActionCreator中使用postHttpLoadingAction(RxAction, Observable<T>)方法。 操作開始時,傳送進度開始通知RxLoading; 操作完成,傳送封裝介面返回結果的RxAction(包含TagLoginAction.LOGIN); 操作結束後,傳送進度結束通知RxLoading

    @Override
    public void login(String username, String password) {
        RxAction rxAction = newRxAction(LOGIN);
        postHttpLoadingAction(rxAction, mWanApi.login(username, password).flatMap(verifyResponse()));
    }
複製程式碼
  1. View

BaseActivity中全域性響應RxLoading

    @Subscribe(sticky = true)
    public void onRxLoading(@NonNull RxLoading rxLoading) {
        if (rxLoading.isLoading()) {
            //顯示進度框
        } else {
            //隱藏進度框
        }
    }
複製程式碼

或者在特定 View LoginActivity中重寫onRxLoading(RxLoading)方法,單獨響應Tag為LoginAction.LOGINRxLoading

    @Override
    @Subscribe(sticky = true)
    public void onRxLoading(@NonNull RxLoading rxLoading) {
        if (TextUtils.equals(rxLoading.getTag(), LoginAction.LOGIN)) {
            if (rxLoading.isLoading()) {
                //顯示進度框
            } else {
                //隱藏進度框
            }
        }
    }
複製程式碼

功能實現3:操作異常RxError

RxActionCretorpostHttpAction(RxAction, Observable<T>)postHttpLoadingAction(RxAction, Observable<T>)方法,如果有異常,會傳送操作異常通知RxError。 可以在BaseActivity中全域性響應RxError

    @Subscribe(sticky = true)
    public void onRxError(@NonNull RxError rxError) {
        Throwable throwable = rxError.getThrowable();
        if (throwable instanceof CommonException) {
            Toast.makeText(this, ((CommonException) throwable).message(), Toast.LENGTH_SHORT).show();
        } else if (throwable instanceof retrofit2.HttpException) {
            Toast.makeText(this, ((retrofit2.HttpException) throwable).code() + ":伺服器問題", Toast.LENGTH_SHORT).show();
        } else if (throwable instanceof SocketException) {
            Toast.makeText(this, "網路異常!", Toast.LENGTH_SHORT).show();
        } else if (throwable instanceof UnknownHostException) {
            Toast.makeText(this, "網路異常!", Toast.LENGTH_SHORT).show();
        } else if (throwable instanceof SocketTimeoutException) {
            Toast.makeText(this, "連線超時!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, throwable.toString(), Toast.LENGTH_SHORT).show();
        }
    }
複製程式碼

或者在特定 View LoginActivity中重寫onRxError(RxError)方法,單獨響應Tag為LoginAction.LOGINRxError

    @Override
    @Subscribe(sticky = true)
    public void onRxError(@NonNull RxError rxError) {
        if (TextUtils.equals(rxError.getTag(), LoginAction.LOGIN)) {
           //單獨處理操作異常...
        }
    }
複製程式碼

功能實現4:異常重試RxRtry

  1. ActionCreator

FriendActionCreator中使用postHttpRetryAction(RxAction, Observable<T>)方法,如果操作有異常,會傳送異常重試通知RxRetry

    @Override
    public void getFriendList() {
        RxAction rxAction = newRxAction(FriendAction.GET_FRIEND_LIST);
        postHttpRetryAction(rxAction, mWanApi.getFriendList());
    }
複製程式碼
  1. View

BaseActivity中全域性響應RxRetry,可以使用RxActionCreator中的postRetryAction(RxRetry)方法重試。

    @Subscribe(sticky = true)
    public void onRxRetry(@NonNull RxRetry rxRetry) {
        CoordinatorLayout coordinatorLayout = findViewById(R.id.cdl_content);
        if (coordinatorLayout == null) {
            return;
        }
        Snackbar snackbar = Snackbar.make(coordinatorLayout, rxRetry.getTag(), Snackbar.LENGTH_INDEFINITE);
        snackbar.setAction("Retry", v -> mCommonActionCreatorLazy.get().postRetryAction(rxRetry)).show();
    }
複製程式碼

或者在特定 View 中重寫onRxRetry(RxRetry)方法,單獨響應特定Tag的RxRetry

    @Override
    @Subscribe(sticky = true)
    public void onRxRetry (@NonNull RxRetry rxRetry) {
        if (TextUtils.equals(rxRetry.getTag(), FriendAction.GET_FRIEND_LIST)) {
            //單獨處理異常重試...
        }
    }
複製程式碼

原始碼

在開源模組化框架RxFluxArchitecture中,歡迎大家指正點贊。可以提取有用的程式碼,單獨編寫!

相關文章