Rxjava 2.0封裝專案例項
阿新 • • 發佈:2019-02-15
簡述
現在的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;
}
}