1. 程式人生 > >Rxjava 2.0封裝專案例項

Rxjava 2.0封裝專案例項

簡述

  • 現在的Android客戶端專案中運用RxJava+Retrofit2基本上已經是主流了。

  • RxJava的優點就不贅述了,對於RxJava還不熟悉的可以在CSDN多找找相關的文章,都寫得很好。

  • 如果不對RxJava的Observer二次封裝的話,每次新建訂閱都要加執行緒切換,複寫方法,比較繁瑣。所以我們就有一個二次封裝的需求。我將專案中我設計的封裝分享出來,至於為什麼要這麼封裝,我在原始碼裡面加註釋,相信大家應該能看懂。

程式碼結構

  • 主要封裝就在RxUtil中,方法都一併註釋了。也可參考原始碼地址。
  • 目前使用過程中還沒有出現不能滿足要求的情況,後續都會一直迭代此封裝。

程式碼檔案主要有
RxUtil

package custom.sunday.com.sharedemo.component.rx;

import android.support.annotation.StringRes;
import android.text.TextUtils;
import android.util.Log;

import java.util.List;

import custom.sunday.com.sharedemo.HomeApplication;
import custom.sunday.com.sharedemo.R;
import io.reactivex.Observable;
import
io.reactivex.ObservableSource; import io.reactivex.ObservableTransformer; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** * Created by Administrator on 2017/8/14. */
public class RxUtil { /** * 執行緒切換,用一個方法代替,免去手抖打錯執行緒 * */ public static <T> ObservableTransformer<T, T> applySchedulers() { return new ObservableTransformer<T, T>() { @Override public Observable<T> apply(Observable<T> observable) { return observable.subscribeOn(Schedulers.io()). observeOn(AndroidSchedulers.mainThread()); } }; } /** * RxJava2.0中不允許傳送空指標,所以需要在這裡判斷如果為空,則傳送empty * 後臺格式固定為RootBean * private String error; //錯誤碼 * private String logID; //除錯ID * private String desc; //詳細描述 * private T result; //我們關心的資料 * 我們只對資料感興趣,所以使用此方法轉換Observable只拿result * */ public static <T> ObservableTransformer<RootBean<T>, T> handleResult() { return new ObservableTransformer<RootBean<T>, T>() { @Override public Observable<T> apply(Observable<RootBean<T>> rootBeanObservable) { return rootBeanObservable.flatMap(new Function<RootBean<T>, Observable<T>>() { @Override public Observable<T> apply(RootBean<T> rootBean) { if (rootBean.getError().equals(HttpCode.SUCCESS)) { if (rootBean.getResult() == null) { return Observable.empty(); } else { return Observable.just(rootBean.getResult()); } } else { return Observable.error(new NormalException( rootBean.getError(), rootBean.getDesc(), rootBean.getLogID())); } } }); } }; } /** * PageData * private int pageTotal; * private int pageNo; * private List<T> pageData; * 同樣的,在APP中分頁資料很常見,所以封裝了PageData,直接將資料變換為List * */ public static <T> ObservableTransformer<RootBean<PageData<T>>, List<T>> handlePageResult() { return new ObservableTransformer<RootBean<PageData<T>>, List<T>>() { @Override public ObservableSource<List<T>> apply(Observable<RootBean<PageData<T>>> observable) { return observable.flatMap(new Function<RootBean<PageData<T>>, ObservableSource<List<T>>>() { @Override public ObservableSource<List<T>> apply(RootBean<PageData<T>> rootBean) throws Exception { if (rootBean.getError().equals(HttpCode.SUCCESS)) { if (rootBean.getResult() == null) { return Observable.empty(); } else { return Observable.just(rootBean.getResult().getPageData()); } } else { return Observable.error(new NormalException( rootBean.getError(), rootBean.getDesc(), rootBean.getLogID())); } } }); } }; } /** * 這裡有一個重要的介面RxLife,此RxLife由baseActivity或者baseFragment實現, * 用於記錄Disposable來實現介面和請求的生命週期同步,當在網路請求中時,離開介面,此時自動取消訂閱 * 為什麼要實現Disposable介面?是因為取消訂閱後我們不能收到通知,所以實現Disposable後,將自身傳入, * 取消訂閱時會回撥dispose,用於介面更新 * **/ public abstract static class SimpleObserver<T> implements Observer<T>, Disposable { private String tag; private RxLife mRxLife; private boolean haveLoading = true; private Disposable disposable; private int resNetDisable = R.string.net_disable_tip; private int resNetNotWork = R.string.net_not_work_tip; public SimpleObserver(RxLife rxLife) { mRxLife = rxLife; } /** * @param tag * 除錯異常結果,傳入TAG,可以過濾多餘資訊 * */ public SimpleObserver(RxLife rxLife, String tag) { mRxLife = rxLife; this.tag = tag; } /** * @param haveLoading * * **/ public SimpleObserver(RxLife rxLife, boolean haveLoading) { mRxLife = rxLife; this.haveLoading = haveLoading; } /** * 獲取網路中斷提示語,如果介面需要單獨的提示語,則覆寫此方法 */ protected int getResNetDisable() { return resNetDisable; } /** * 獲取網路異常提示語,如果介面需要單獨的提示語,則覆寫此方法 */ protected int getResNetNotWork() { return resNetNotWork; } /** * 隱藏網路異常提示,如果不需要網路異常提示,則覆寫此方法改為true * @return */ public boolean isHideErrorTip() { return false; } @Override public void onSubscribe(Disposable disposable) { this.disposable = disposable; if (mRxLife != null) { mRxLife.addDisposable(this); if (haveLoading) { mRxLife.showLoading(); } } } @Override public void onComplete() { if (mRxLife != null) { mRxLife.removeDisposable(this); if (haveLoading) { mRxLife.hideLoading(); } } else { disposable.dispose(); } } @Override public void onError(Throwable e) { e.printStackTrace(); if (mRxLife != null) { mRxLife.removeDisposable(this); if (haveLoading) { mRxLife.hideLoading(); } } else { disposable.dispose(); } //look HttpCode.java String errorMsg = e.getMessage(); if (e instanceof NormalException) { if (errorMsg.equals(HttpCode.RELOGIN)) { //HomeApplication.getInstance().logout(); } else if (errorMsg.equals(HttpCode.SERVICE_ERROR)) { if (mRxLife != null && !isHideErrorTip()) { mRxLife.showErrorTips(resNetNotWork); } } } else { if (mRxLife != null && !isHideErrorTip()) { // if (!NetworkUtil.getInstance(HomeApplication.getInstance().getApplicationContext()).isNetworkConnected()) { // mRxLife.showErrorTips(getResNetDisable()); //網路斷開提示 // } else { // mRxLife.showErrorTips(getResNetNotWork()); //網路無法訪問提示 // } } } onErrorMsg(errorMsg); } protected void onErrorMsg(String msg) { if (tag != null) { Log.e("RxUtil", "tag = " + tag + " onErrorMsg | = " + msg); } else { Log.e("RxUtil", "onErrorMsg | = " + msg); } } @Override public void dispose() { disposable.dispose(); } @Override public boolean isDisposed() { return disposable.isDisposed(); } @Override public void onNext(T t) { onResult(t); } abstract public void onResult(T t); } public static class NormalException extends Exception { private String desc; private String logId; public NormalException(String msg) { super(msg); } public NormalException(String msg, String desc, String logId) { this(msg); this.desc = desc; this.logId = logId; } public String getLogId() { return logId; } } }

RxLife

public interface RxLife {

    void showLoading();

    void hideLoading();

    void showNetworkErrorTips();

    void showErrorTips(int resId);

    void addDisposable(Disposable disposable);

    void removeDisposable(Disposable disposable);

    void disposableAll();
}

RootBean

public class RootBean<T> {
    private String error;
    private String logID;
    private String desc;
    private T result;

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getLogID() {
        return logID;
    }

    public void setLogID(String logID) {
        this.logID = logID;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }
}

PageData

public class PageData<T> {
    private int pageTotal;
    private int pageNo;
    private List<T> pageData;
    public void setPageTotal(int pageTotal) {
        this.pageTotal = pageTotal;
    }
    public int getPageTotal() {
        return pageTotal;
    }

    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }
    public int getPageNo() {
        return pageNo;
    }

    public void setPageData(List<T> pageData) {
        this.pageData = pageData;
    }
    public List<T> getPageData() {
        return pageData;
    }
}