聲明:本文只講封裝沿猜,基本用法請(qǐng)參考官方文檔或者其他文章~
0. 依賴(lài)
2.0已出枚荣,但是暫時(shí)還沒(méi)有來(lái)得及去看;所以還是那目前項(xiàng)目中在用的來(lái)講吧啼肩。
compile 'io.reactivex:rxjava:1.2.4'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.artemzin.rxjava:proguard-rules:1.2.7.0'
compile 'com.trello:rxlifecycle:1.0'
compile 'com.trello:rxlifecycle-components:1.0'
compile 'com.jakewharton.rxbinding:rxbinding:1.0.0'
以下展示目前項(xiàng)目中最常用的幾個(gè)例子:
1. View相關(guān)
點(diǎn)擊事件
- 使用
Rx.clicks(mBtn, this, v -> doAction());
- 功能點(diǎn)
- 過(guò)濾500ms內(nèi)的重復(fù)點(diǎn)擊橄妆;
- 綁定當(dāng)前activity或者fragment的生命周期,避免內(nèi)存泄漏祈坠;
- 封裝
//view點(diǎn)擊事件害碾,500毫秒過(guò)濾重復(fù)點(diǎn)擊
public static void clicks(View view, BaseActivity activity, final Action1<Void> onNext) {
RxView.clicks(view)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.compose(activity.bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onNext, e -> e.printStackTrace());
}
輸入框文字變動(dòng)
- 使用
Rx.afterTextChangeEvents(this, mEditText, event -> doAction());
- 功能點(diǎn)
- 過(guò)濾500ms內(nèi)的請(qǐng)求,尤其是當(dāng)輸入框文字變動(dòng)后需要進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí)赦拘,可以有效避免產(chǎn)生大量請(qǐng)求慌随;
- 綁定當(dāng)前activity或者fragment的生命周期,避免內(nèi)存泄漏躺同;
- 封裝
//TextView watcher阁猜,間隔500毫秒
public static void afterTextChangeEvents(BaseActivity activity, TextView textView, Action1<TextViewAfterTextChangeEvent> onNext) {
RxTextView.afterTextChangeEvents(textView)
.throttleLast(500, TimeUnit.MILLISECONDS)
.compose(activity.bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onNext, e -> e.printStackTrace());
}
2. 網(wǎng)絡(luò)請(qǐng)求(劃重點(diǎn)!)
- 使用
API.uploadImg(picInfo) //以上傳圖片為例
.compose(RxTransformers.doApi(this))
.subscribe((Result result) -> {
//to do
});
簡(jiǎn)潔到爆炸有木有!K褡选蹦漠!
- 功能點(diǎn)
- 保留原有的鏈?zhǔn)秸{(diào)用方式;
-
subscribe()
中可以?xún)H僅傳入onNext
车海,onError
和onComplete
可選笛园,所以再加上lamda加持,做到代碼最簡(jiǎn)潔~(原先若只傳入onNext
而不傳入onError
,當(dāng)網(wǎng)絡(luò)異呈讨ィ或者onNext
執(zhí)行發(fā)生異常時(shí)研铆,會(huì)拋出OnErrorNotImplementedException
); - 線(xiàn)程切換州叠;
- 綁定當(dāng)前頁(yè)面生命周期棵红,當(dāng)onPause時(shí),停止未完成的請(qǐng)求(拋掉已經(jīng)請(qǐng)求來(lái)的response咧栗,不進(jìn)行處理)逆甜;
- 請(qǐng)求結(jié)果統(tǒng)一預(yù)處理:
5.1 網(wǎng)絡(luò)異常處理與上報(bào)虱肄;
5.2 接口請(qǐng)求錯(cuò)誤信息展示;
5.3 loading UI的顯示和隱藏交煞;
5.4 token失效后的統(tǒng)一處理咏窿;
- 封裝
若想理解以下封裝原理,請(qǐng)先通讀compose()
和lift()
兩個(gè)操作符的源碼素征;
API.uploadImg(picInfo)
是基于retrofit的封裝
此處省略
compose()
操作符中傳入的自定義Transformer
public class RxTransformers {
public static <T> Observable.Transformer<T, T> io_main() {
return (Observable<T> observable) -> observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public static <T> Observable.Transformer<T, T> doApi(BaseActivity activity, HttpResultInterceptor.Type type) {
return (Observable<T> observable) -> observable
.compose(io_main())//線(xiàn)程切換
.compose(activity.bindToLifecycle())//生命周期
.lift(HttpResultInterceptor.get(activity, type));//請(qǐng)求結(jié)果預(yù)處理
}
public static <T> Observable.Transformer<T, T> doApi(BaseActivity activity) {
return doApi(activity, HttpResultInterceptor.Type.ALL);
}
}
線(xiàn)程切換和頁(yè)面生命周期綁定沒(méi)啥好講的集嵌,重點(diǎn)是lift()
中傳入的自定義operator
lift(HttpResultInterceptor.get(activity, type));
請(qǐng)求結(jié)果預(yù)處理
/**
* Created by Jessewo on 2017/7/25.
* <p>
* 1.API鏈?zhǔn)秸{(diào)用
* 2.lamda表達(dá)式(第一層subscriber,可以只實(shí)現(xiàn)onNext(),onError/onComplete非必須)
*/
public class HttpResultInterceptor {
private static final String TAG = "HttpResultInterceptor";
public enum Type {
/**
* 1. filter exception and show exception msg when onError<br/>
* 2. show loading when onStart, and hide when onComplete or onError<br/>
* 3. show error message when onNext
*/
ALL,
/**
* 1. filter exception and show exception msg when onError<br/>
* 2. show error message when onNext
*/
ERROR_MSG,
/**
* 1. filter exception and show exception msg when onError<br/>
* 2. show loading when onStart, and hide when onComplete or onError
*/
LOADING,
/**
* 1. filter exception and show exception msg when onError
*/
NONE
}
public static Observable.Operator get(HttpResultHandler handler, Type type) {
return new OperatorHttpResult(handler, type);
}
private static class OperatorHttpResult<T> implements Observable.Operator<T, T>, Subscription {
private SoftReference<HttpResultHandler> mHandler;
private Type mType;
OperatorHttpResult(HttpResultHandler httpResultHandler) {
mHandler = new SoftReference<>(httpResultHandler);
}
OperatorHttpResult(HttpResultHandler httpResultHandler, Type type) {
mHandler = new SoftReference<>(httpResultHandler);
mType = type;
}
@Override
public Subscriber<? super T> call(Subscriber<? super T> subscriber) {
HttpResultSubscriber<? super T> parent = new HttpResultSubscriber<>(subscriber, mHandler, mType);
//parent subscriber 獨(dú)立控制 unSubscribe行為
parent.add(this);
return parent;
}
@Override
public void unsubscribe() {
mHandler.clear();
}
@Override
public boolean isUnsubscribed() {
return mHandler.get() == null;
}
}
/**
* 異常處理原則與safeSubscriber稍有不同:<br/>
* 1. onNext所有異常抓取->onError;(同)<br/>
* 2. onComplete所有異常拋出;(同)<br/>
* 3. onError拋出除了OnErrorNotImplementedException之外的所有異常;(不同)
*/
private static class HttpResultSubscriber<T> extends Subscriber<T> {
private Subscriber<? super T> mChild;
private SoftReference<HttpResultHandler> mHandler;
private boolean showProgress;
private boolean showError;
private boolean done;
HttpResultSubscriber(Subscriber<? super T> child,
SoftReference<HttpResultHandler> preHandler,
Type type) {
mChild = child;
mHandler = preHandler;
switch (type) {
case ERROR_MSG:
showProgress = false;
showError = true;
break;
case LOADING:
showProgress = true;
showError = false;
break;
case NONE:
showProgress = false;
showError = false;
break;
default://all
showProgress = true;
showError = true;
break;
}
}
@Override
public void onStart() {
//main thread
showProgress();
}
@Override
public void onCompleted() {
if (done || isUnsubscribed() || mChild.isUnsubscribed())
return;
done = true;
try {
dismissProgress();
mChild.onCompleted();
} finally {
try {
unsubscribe();
} catch (Throwable e) {
RxJavaHooks.onError(e);
throw new OnCompletedFailedException(e.getMessage(), e);
}
}
}
@Override
public void onError(Throwable e) {
if (done || isUnsubscribed() || mChild.isUnsubscribed())
return;
done = true;
try {
dismissProgress();
if (e instanceof OnErrorNotImplementedException) {
e = e.getCause();
}
e.printStackTrace();
String error = App.getInstance().getString(R.string.error_network);
if (e instanceof SocketTimeoutException) {
ToastUtil.show(error + "(" + NETWORK_ERROR_TIMEOUT + ")");
} else if (e instanceof ConnectException) {
ToastUtil.show(error + "(" + NETWORK_ERROR_INTERRUPTION + ")");
} else if (e instanceof UnknownHostException
|| (!TextUtils.isEmpty(e.getMessage()) && e.getMessage().contains("No address associated with hostname"))) {
ToastUtil.show(error + "(" + NETWORK_ERROR_UNKNOWN_HOST + ")");
} else {
ToastUtil.show(error + "(" + NETWORK_ERROR_UNKNOWN + ")");
Analytics.getInstance().onError(e);//對(duì)于非常規(guī)異常上報(bào)后臺(tái)監(jiān)控
}
mChild.onError(e);
} catch (OnErrorNotImplementedException e2) {
//ignore
LOG.d(TAG, "onError: OnErrorNotImplementedException");
} finally {
try {
unsubscribe();
} catch (Throwable e3) {
RxJavaHooks.onError(e3);
throw new OnErrorFailedException(e3.getMessage(), e3);
}
}
}
@Override
public void onNext(T t) {
if (done || isUnsubscribed() || mChild.isUnsubscribed())
return;
try {
if (showError) {
if (t instanceof Result) {
Result result = (Result) t;
checkResult(result);
} else if (t instanceof MixResult) {
MixResult mixResult = (MixResult) t;
Result result1 = mixResult.getResult1();
Result result2 = mixResult.getResult2();
if (result1 != null && result2 != null) {
checkResult(result1);
checkResult(result2);
}
}
}
mChild.onNext(t);
} catch (Throwable e) {
onError(e);
}
}
private void checkResult(Result result) {
int status = result.getStatus();
switch (status) {
case API.SUCCESS_CODE:
case API.SKIP_CODE:
break;
case API.RELOGIN_CODE:
//token失效
String msg = result.getMsg();
HttpResultHandler preHandler = mHandler.get();
if (preHandler != null) {
preHandler.onTokenInvalid(msg);
} else {
ToastUtil.show(msg);
}
break;
default:
ErrorMsg.getInstance().show(result);
break;
}
}
private void showProgress() {
if (showProgress && mHandler.get() != null)
mHandler.get().showProgress();
}
private void dismissProgress() {
if (showProgress && mHandler.get() != null)
mHandler.get().dismissProgress();
}
}
//BaseActivity或者BaseFragment需要實(shí)現(xiàn)此接口
public interface HttpResultHandler {
void showProgress();
void dismissProgress();
void onTokenInvalid(String msg);
//其他功能可擴(kuò)展
// void showMessage(String msg);
// void lowerVersion();
}
}