經(jīng)過前面的封裝,我的網(wǎng)絡(luò)請求庫已經(jīng)使用了很長一段時間了,但還是覺得寫的代碼多了點,而且還不支持緩存的問題.
今天我將繼續(xù)分享我的后續(xù)優(yōu)化和緩存的解決方案.
優(yōu)化
為了讓在Activity和Fragment中發(fā)的網(wǎng)絡(luò)請求自動綁定生命周期,而不需要每次都重復的寫同一行代碼,我修改了原來RxUtil
類,下面我附上目前這個類的完整代碼.
public class RxUtil {
public static <T> LifecycleTransformer<T> bindToLifecycle(LifecycleProvider provider) {
if (provider instanceof RxAppCompatActivity) {
return ((RxAppCompatActivity) provider).bindToLifecycle();
} else if (provider instanceof RxFragment) {
return ((RxFragment) provider).bindToLifecycle();
} else {
throw new IllegalArgumentException("class must extents RxAppCompatActivity or RxFragment");
}
}
public static <T> LifecycleTransformer<T> bindToLifecycle(LifecycleProvider provider, ActivityEvent event) {
if (provider instanceof RxAppCompatActivity) {
return ((RxAppCompatActivity) provider).bindUntilEvent(event);
} else {
throw new IllegalArgumentException("class must extents RxAppCompatActivity");
}
}
public static <T> LifecycleTransformer<T> bindToLifecycle(LifecycleProvider provider, FragmentEvent event) {
if (provider instanceof RxFragment) {
return ((RxFragment) provider).bindUntilEvent(event);
} else {
throw new IllegalArgumentException("class must extents RxFragment");
}
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(RxUtil.<T>bindToLifecycle(provider));
}
};
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider, final ActivityEvent event) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(RxUtil.<T>bindToLifecycle(provider, event));
}
};
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider, final FragmentEvent event) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(RxUtil.<T>bindToLifecycle(provider, event));
}
};
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider, @NonNull final Dialog dialog) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.delay(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull final Disposable disposable) throws Exception {
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
disposable.dispose();
}
});
dialog.show();
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnTerminate(new Action() {
@Override public void run() throws Exception {
dialog.dismiss();
}
})
.compose(RxUtil.<T>bindToLifecycle(provider));
}
};
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider, final ActivityEvent event, @NonNull final Dialog dialog) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.delay(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull final Disposable disposable) throws Exception {
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
disposable.dispose();
}
});
dialog.show();
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnTerminate(new Action() {
@Override public void run() throws Exception {
dialog.dismiss();
}
})
.compose(RxUtil.<T>bindToLifecycle(provider, event));
}
};
}
public static <T> ObservableTransformer<T, T> applySchedulers(final LifecycleProvider provider, final FragmentEvent event, @NonNull final Dialog dialog) {
return new ObservableTransformer<T, T>() {
@Override public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.delay(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull final Disposable disposable) throws Exception {
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
disposable.dispose();
}
});
dialog.show();
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnTerminate(new Action() {
@Override public void run() throws Exception {
dialog.dismiss();
}
})
.compose(RxUtil.<T>bindToLifecycle(provider, event));
}
};
}
}
對于這個類,我自己都覺得挺蛋疼的 ,平白無故的寫了很多重復的代碼.主要原因在于rxlifecycle2-android
這個包中的ActivityEvent
和FragmentEvent
是兩個獨立的枚舉沒法合并,為了保證傳入的參數(shù)安全,只能重載方法了.
此外這次新增了RxLifecycle中的bindUntilEvent()的支持.
緩存
緩存這部分,因為用了RxJava很自然的就想到去用RxCache,但是后來才發(fā)現(xiàn)里面有好大的一個坑,而RxCache把這個鍋推給了Gson.
如果我們的實體類中使用int
類型,在正常的網(wǎng)絡(luò)請求中能正常的獲得解析,但是在配置了RxCache后,就會出現(xiàn)返回的對象類型發(fā)生了變化,變成了LinkedTreeMap
,坑爹有木有...為啥會這樣呢?
當查看了緩存的內(nèi)容后,你會發(fā)現(xiàn)原本的int
類型變成了double
了,比如用戶的年齡9
變成了9.0
,這樣原來的實體類就解析不了.只有另辟捷徑了----使用okhttp3
的緩存方法,Retrofit2
支持給請求添加自定義的header,引用自己項目中的一個接口:
@GET("api/car/queryCarBrand")
@Headers("Cache-Control: public, max-age=60")
Observable<Result<List<CarBrand>>> queryCarBrand();
上面的接口添加了緩存控制,在第一次網(wǎng)絡(luò)請求被緩存后,在60秒內(nèi)不會再請求服務器而是讀取緩存中的數(shù)據(jù).
為此我們需要再修改兩個地方:
一. Retrofit初始化的時候
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
...
okHttpBuilder.cache(new Cache(file,size));//file是緩存路徑,size緩存池大小
...
二. 請求頭的修改.
一般情況下應該是服務器告訴我們是否該緩存這次的請求結(jié)果,雖然我們現(xiàn)在請求接口上配置了請求頭,但是服務器不知道或者沒有修改返回的請求頭,我們拿到的返回結(jié)果請求頭中依然沒有Cache-Control
,這樣okhttp
依然不會緩存請求結(jié)果.
我的處理方式是在修改請求頭攔截器
public class HeaderInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
ArrayMap<String, String> headers = BaseApp.getAppContext().getRequestHeader();
//如果公共請求頭不為空,則構(gòu)建新的請求
if (headers != null) {
for (String key : headers.keySet()) {
requestBuilder.addHeader(key, headers.get(key));
}
}
Request request = requestBuilder.build();
Response.Builder responseBuilder = chain.proceed(request).newBuilder();
if (!TextUtils.isEmpty(request.cacheControl().toString())) {
responseBuilder.removeHeader("Pragma").removeHeader("Cache-Control")
.header("Cache-Control", "public, max-age=" + request.cacheControl().maxAgeSeconds());
}
return responseBuilder.build();
}
}
根據(jù)Request
中是否有Cache-Control
來手動修改Response
,這樣就做了是否緩存每次的請求結(jié)果緩存多久完全由我們自己來控制了.
然后在第一步中增加或修改
okHttpBuilder.addNetworkInterceptor(new HeaderInterceptor());
這樣就能正常緩存請求了.
后續(xù)再有更新或優(yōu)化,會再次更新文章~