rxjava+retrofit處理網(wǎng)絡(luò)請求
在使用rxjava+retrofit處理網(wǎng)絡(luò)請求的時候,一般會采用對觀察者進行封裝扔水,實現(xiàn)代碼復(fù)用和拓展痛侍。一種可行的封裝如下:
- 基類observer
public abstract class BaseObserver<T> implements Observer<T> {
protected String errMsg = "";
protected Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(T t) {
}
@Override
public void onError(Throwable e) {
LogUtils.d("Subscriber onError", e.getMessage());
if (!NetworkUtils.isConnected()) {
errMsg = "網(wǎng)絡(luò)連接出錯,";
} else if (e instanceof APIException) {
APIException exception = (APIException) e;
errMsg = exception.getMessage() + ", ";
} else if (e instanceof HttpException) {
errMsg = "網(wǎng)絡(luò)請求出錯,";
} else if (e instanceof IOException) {
errMsg = "網(wǎng)絡(luò)出錯,";
}
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
@Override
public void onComplete() {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}
- 封裝請求(登錄為例) 這里userService是retrofit接口類
/**
* 登錄
* @param phone 賬號
* @param password 密碼
* @param observer 觀察者
*/
public void login(String phone, String password, BaseObserver<ResponseBean<UidBean>> observer) {
// userService.login(new RequestUserBean(phone, EncryptUtils.encryptMD5ToString(password)))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
- 方法調(diào)用
APIUser.getInstance().login(phone, password, new BaseObserver<ResponseBean<UidBean>>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
}
@Override
public void onNext(ResponseBean<UidBean> responseBean) {
ToastUtils.showShort("登錄成功");
}
@Override
public void onError(Throwable e) {
super.onError(e);
ToastUtils.showShort(errMsg+"登錄失敗");
}
});
網(wǎng)上大家對rxjava+retrofit好的封裝很多,我這里不再贅述魔市。
關(guān)于disposable
rxjava雖然好用主届,但是總所周知,容易遭層內(nèi)存泄漏待德。也就說在訂閱了事件后沒有及時取閱岂膳,導(dǎo)致在activity或者fragment銷毀后仍然占用著內(nèi)存,無法釋放磅网。而disposable便是這個訂閱事件谈截,可以用來取消訂閱。但是在什么時候取消訂閱呢涧偷?我知道有兩種方式:
- 使用CompositeDisposable
看源碼簸喂,CompositeDisposable的介紹很簡單
A disposable container that can hold onto multiple other disposables and offers O(1) add and removal complexity.
一個disposable的容器,可以容納多個disposable燎潮,添加和去除的復(fù)雜度為O(1)喻鳄。
這里需要注意的是在該類的addAll
方法有這么一句注釋
Atomically adds the given array of Disposables to the container or disposes them all if the container has been disposed
也就是說,如果這個CompositeDisposable容器已經(jīng)是處于dispose的狀態(tài)确封,那么所有加進來的disposable都會被自動切斷除呵。
所以說可以創(chuàng)建一個BaseActivity
再菊,用CompositeDisposable來管理訂閱事件disposable,然后在acivity銷毀的時候颜曾,調(diào)用compositeDisposable.dispose()
就可以切斷所有訂閱事件纠拔,防止內(nèi)存泄漏。
- 在oError和onComplete后調(diào)用
disposable.dispose();
泛豪,也就是上面我給的例子中的方法稠诲。
- 在oError和onComplete后調(diào)用
查看源碼,ObservableCreate的靜態(tài)類CreateEmitter就是這種方式實現(xiàn)的诡曙。同時也可以看到臀叙,onError和onComplete不可以同時調(diào)用的原因:每次掉用過onError或onComplete其中一個方法后,就會掉用dispose()
方法价卤,此時訂閱取消劝萤,自然也就不能掉用另一個方法了
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
private static final long serialVersionUID = -3434801548987643227L;
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
if (t == null) {
t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
}
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
dispose();
}
} else {
RxJavaPlugins.onError(t);
}
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
@Override
public void setDisposable(Disposable d) {
DisposableHelper.set(this, d);
}
@Override
public void setCancellable(Cancellable c) {
setDisposable(new CancellableDisposable(c));
}
@Override
public ObservableEmitter<T> serialize() {
return new SerializedEmitter<T>(this);
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
除此之外,在github發(fā)現(xiàn)一個開源庫RxLifecyclee慎璧,粗略了解發(fā)現(xiàn)他實現(xiàn)的原理是綁定acvitvity是生命周期稳其,在onStart中綁定就在onStop中解綁,其他onResume炸卑,onCreate同理既鞠。這個和第一種方式似乎又差不多,只不過第一種方式簡單盖文,只在ondestory的時候銷毀所有事件嘱蛋。
所以那兩種方法哪種更好,我也不是很清楚五续。等到踩到什么坑了可能就知道了洒敏。
如果某位大佬知道,希望不吝指教疙驾。