CSDN
博客發佈了一系列的RxJava+Retrofit+OkHttp
深刻淺出-終極封裝是否是很眼熟,是的仍是它,不過是不一樣的配方。以前發出後收到不少朋友的關注,本來只是本身學習後的一些經驗總結,可是有同窗運用到實戰當中,這讓我很惶恐,全部後續一直更新了不少次版本,有些地方不免有所變更致使以前的博客有所出入,正好最近受到掘金邀請內測博客,因此決定從新寫一版,按照最後迭代完成的封裝詳細的講述一遍,歡迎你們關注!html
注意:因爲本章的特殊性,後續文章比較長並且複雜,涉及內容也不少,因此你們準備好茶水,前方高能預警。java
封裝完之後,具備以下功能:git
1.Retrofit+Rxjava+okhttp基本使用方法
2.統一處理請求數據格式
3.統一的ProgressDialog和回調Subscriber處理
4.取消http請求
5.預處理http請求
6.返回數據的統一判斷
7.失敗後的retry封裝處理
8.RxLifecycle管理生命週期,防止泄露複製代碼
封裝後http請求代碼以下github
// 完美封裝簡化版
private void simpleDo() {
SubjectPost postEntity = new SubjectPost(simpleOnNextListener,this);
postEntity.setAll(true);
HttpManager manager = HttpManager.getInstance();
manager.doHttpDeal(postEntity);
}
// 回調一一對應
HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() {
@Override
public void onNext(List<Subject> subjects) {
tvMsg.setText("已封裝:\n" + subjects.toString());
}
/*用戶主動調用,默認是不須要覆寫該方法*/
@Override
public void onError(Throwable e) {
super.onError(e);
tvMsg.setText("失敗:\n" + e.toString());
}
};複製代碼
是否是很簡單?你可能說這還簡單,好我們對比一下正常使用Retrofit
的方法數據庫
/** * Retrofit加入rxjava實現http請求 */
private void onButton9Click() {
//手動建立一個OkHttpClient並設置超時時間
okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5, TimeUnit.SECONDS);
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(HttpManager.BASE_URL)
.build();
/ 加載框
final ProgressDialog pd = new ProgressDialog(this);
HttpService apiService = retrofit.create(HttpService.class);
Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);
observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Subscriber<RetrofitEntity>() {
@Override
public void onCompleted() {
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
}
@Override
public void onError(Throwable e) {
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
}
@Override
public void onNext(RetrofitEntity retrofitEntity) {
tvMsg.setText("無封裝:\n" + retrofitEntity.getData().toString());
}
@Override
public void onStart() {
super.onStart();
pd.show();
}
}
);
}複製代碼
可能你發現確是代碼有點多,可是更加可怕的是,若是你一個activity或者fragment中屢次須要http請求,你須要屢次重複的寫回調處理(一個回到就有4個方法呀!!!!反正我是忍受不了),並且以上處理尚未作過多的判斷和錯誤校驗就如此複雜!~好了介紹完了,開始我們的優化之路吧!json
RxJava
若是你對RxJava
不瞭解,好吧騷年趕快學學吧,否則真會out
了,下面給出博主當初學習RxJava
的一些資源:api
Retrofit
咱家今天的主角來了,我們也深刻淺出一下了解下Retrofit
使用,前方高能,若是你是深度Retrofit
選手請直接跳過本節!!!緩存
<uses-permission android:name="android.permission.INTERNET"/>複製代碼
/*rx-android-java*/
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.trello:rxlifecycle:1.0'
compile 'com.trello:rxlifecycle-components:1.0'
/*rotrofit*/
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.google.code.gson:gson:2.8.0'複製代碼
這裏介紹一些經常使用的註解的使用服務器
@Query
、@QueryMap
:用於Http Get
請求傳遞參數
@Field
:用於Post
方式傳遞參數,須要在請求接口方法上添加@FormUrlEncoded
,即以表單的方式傳遞參數
@Body
:用於Post
,根據轉換方式將實例對象轉化爲對應字符串傳遞參數.好比Retrofit
添加GsonConverterFactory
則是將body
轉化爲gson
字符串進行傳遞
@Path
:用於URL
上佔位符
@Part
:配合@Multipart
使用,通常用於文件上傳
@Header
:添加http header
@Headers
:跟@Header
做用同樣,只是使用方式不同,@Header
是做爲請求方法的參數傳入,@Headers
是以固定方式直接添加到請求方法上
ReTrofit
基本使用:首先給定一個測試接口文檔,後面的博客中咱們都是用這個接口調試
/** * @api videoLink 50音圖視頻連接 * @url http://www.izaodao.com/Api/AppFiftyToneGraph/videoLink * @method post * @param once_no bool(選填,ture無連接) 一次性獲取下載地址 * @return json array( * ret:1成功,2失敗 * msg:信息 * data:{ * name:視頻名稱 * title:標題 * } )複製代碼
要向一個api發送咱們的網絡請求 ,咱們須要使用Retrofit builder
類並指定service
的base URL
(一般狀況下就是域名)。
String BASE_URL = " http://www.izaodao.com/Api/"
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();複製代碼
service
注意到每一個endpoint
都指定了一個關於HTTP
(GET
, POST
, 等等。) 方法的註解以及用於分發網絡調用的方法。並且這些方法的參數也能夠有特殊的註解。
/** * 接口地址 * Created by WZG on 2016/7/16. */
public interface MyApiEndpointInterface {
@POST("AppFiftyToneGraph/videoLink")
Call<RetrofitEntity> getAllVedio(@Body boolean once_no) }複製代碼
call
而後同步處理處理回調:MyApiEndpointInterface apiService = retrofit.create(MyApiEndpointInterface.class);
Call<RetrofitEntity> call = apiService.getAllVedio(true);
call.enqueue(new Callback<RetrofitEntity>() {
@Override
public void onResponse(Response<RetrofitEntity> response, Retrofit retrofit) {
RetrofitEntity entity = response.body();
Log.i("tag", "onResponse----->" + entity.getMsg());
}
@Override
public void onFailure(Throwable t) {
Log.i("tag", "onFailure----->" + t.toString());
}
});複製代碼
這就是簡單的Retrofit
使用步驟,接下來咱們結合RxJava講述
ReTrofit+Rxjava
基本使用對比以前的Retrofit
使用
service
接口返回信息咱們須要返回一個Observable
對象@POST("AppFiftyToneGraph/videoLink")
Observable<RetrofitEntity> getAllVedioBy(@Body boolean once_no);複製代碼
Retrofit
須要添加對Rxjava
的適配,注意必定要retrofit2
纔有這個功能哦Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(HttpManager.BASE_URL)
.build();複製代碼
RxJava
處理HttpService apiService = retrofit.create(HttpService.class);
Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);
observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Subscriber<RetrofitEntity>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(RetrofitEntity retrofitEntity) {
tvMsg.setText("無封裝:\n" + retrofitEntity.getData().toString());
}
}
);複製代碼
簡單的RxJava
集合Retrofit
的使用就介紹完了,一樣的能夠發現使用起來不少重複性的代碼,並且使用也不是那麼簡單,因此纔有了下面的封裝
先來一張流程圖壓壓驚
首先須要封裝的使咱們的數據類,在數據類中須要封裝請求中用到的相關數據的設置,好比請求參數、方法、加載框顯示設置等等
public abstract class BaseApi<T> implements Func1<BaseResultEntity<T>, T> {
//rx生命週期管理
private SoftReference<RxAppCompatActivity> rxAppCompatActivity;
/*回調*/
private SoftReference<HttpOnNextListener> listener;
/*是否能取消加載框*/
private boolean cancel;
/*是否顯示加載框*/
private boolean showProgress;
/*是否須要緩存處理*/
private boolean cache;
/*基礎url*/
private String baseUrl="http://www.izaodao.com/Api/";
/*方法-若是須要緩存必須設置這個參數;不須要不用設置*/
private String mothed;
/*超時時間-默認6秒*/
private int connectionTime = 6;
/*有網狀況下的本地緩存時間默認60秒*/
private int cookieNetWorkTime=60;
/*無網絡的狀況下本地緩存時間默認30天*/
private int cookieNoNetWorkTime=24*60*60*30;
}複製代碼
註釋很詳細,這裏不具體描述了,因爲這裏是最後封裝完成之後的代碼,因此有些內容本章還會部分不會涉及,由於功能太多,仍是按照一開始的博客章節講解。
api
接口/** * 設置參數 * * @param retrofit * @return */
public abstract Observable getObservable(Retrofit retrofit);複製代碼
經過子類也便是咱們的具體api
接口,經過getObservable
實現service
中定義的接口方法,例如:
public class SubjectPostApi extends BaseApi {
xxxxxxx
xxxxxxx
@Override
public Observable getObservable(Retrofit retrofit) {
HttpPostService service = retrofit.create(HttpPostService.class);
return service.getAllVedioBys(isAll());
}
}複製代碼
經過傳入的Retrofit
對象,能夠隨意切換挑選Service
對象,獲得定義的註解方法,初始完成之後返回Observable
對象。
這裏結合RxJava
的map
方法在服務器返回數據中,統一處理數據處理,因此BaseApi<T> implements Func1<BaseResultEntity<T>, T>
,後邊結合結果處理連接起來使用
@Override
public T call(BaseResultEntity<T> httpResult) {
if (httpResult.getRet() == 0) {
throw new HttpTimeException(httpResult.getMsg());
}
return httpResult.getData();
}複製代碼
因爲測試接口,也是當前咱們公司接口都是有統一規則的,想必你們都有這樣的接口規則,因此纔有這裏的統一判斷,規則以下:
* ret:1成功,2失敗
* msg:信息
* data:{
* name:視頻名稱
* title:標題
* }複製代碼
其實上面的接口文檔中就介紹了,統一先經過ret
判斷,失敗顯示msg
信息,data
是成功後的數據也就是用戶關心的數據,因此可封裝一個結果對象BaseResultEntity
.
/** * 回調信息統一封裝類 * Created by WZG on 2016/7/16. */
public class BaseResultEntity<T> {
// 判斷標示
private int ret;
// 提示信息
private String msg;
//顯示數據(用戶須要關心的數據)
private T data;
xxxxx get-set xxxxx
}複製代碼
這裏結合BaseApi
的Func1
判斷,失敗直接拋出一個異常,交個RxJava
的onError
處理,成功則將用戶關心的數據傳給Gson
解析返回
BaseResultEntity<T>
中的泛型T
也就是咱們所關心的回調數據,一樣也是Gson最後解析返回的數據,傳遞的過程根節點是經過定義service
方法是給定的,例如:
public interface HttpPostService {
@POST("AppFiftyToneGraph/videoLink")
Call<RetrofitEntity> getAllVedio(@Body boolean once_no);
}複製代碼
其中的RetrofitEntity
就是用戶關心的數據類,經過泛型傳遞給最後的接口。
不少兄弟經過QQ羣反饋給我說,使用一個接口須要寫一個對應的api
類繼承BaseApi
是否是很麻煩,我這裏強調一下,這樣封裝是爲了將一個Api
接口做爲一個對象去封裝,我的以爲有必要封裝成一個類,在往後工程日益增長接口隨着增長的同時,對象的作法更加有利於查找接口和修改接口有利於迭代。
首先初始化一個單利方便HttpManager
請求;這裏用了volatile
的對象,不懂的同窗能夠參考個人另外一篇博客
private volatile static HttpManager INSTANCE;
//構造方法私有
private HttpManager() {
}
//獲取單例
public static HttpManager getInstance() {
if (INSTANCE == null) {
synchronized (HttpManager.class) {
if (INSTANCE == null) {
INSTANCE = new HttpManager();
}
}
}
return INSTANCE;
}複製代碼
/** * 處理http請求 * * @param basePar 封裝的請求數據 */
public void doHttpDeal(BaseApi basePar) {
//手動建立一個OkHttpClient並設置超時時間緩存等設置
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(basePar.getConnectionTime(), TimeUnit.SECONDS);
builder.addInterceptor(new CookieInterceptor(basePar.isCache()));
/*建立retrofit對象*/
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(basePar.getBaseUrl())
.build();
/*rx處理*/
ProgressSubscriber subscriber = new ProgressSubscriber(basePar);
Observable observable = basePar.getObservable(retrofit)
/*失敗後的retry配置*/
.retryWhen(new RetryWhenNetworkException())
/*生命週期管理*/
.compose(basePar.getRxAppCompatActivity().bindToLifecycle())
/*http請求線程*/
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
/*回調線程*/
.observeOn(AndroidSchedulers.mainThread())
/*結果判斷*/
.map(basePar);
/*數據回調*/
observable.subscribe(subscriber);
}複製代碼
首先經過api
接口類BaseApi
的實現類中數據初始化OkHttpClient
和Retrofit
對象,其中包含了url
,超時等,接着經過BaseApi
的抽象方法getObservable
獲得Observable
對象,獲得Observable
對象之後,咱們就能隨意的切換現成來處理,整個請求經過compose
設定的rxlifecycle
來管理生命週期,因此不會溢出和泄露無需任何擔憂,最後再服務器數據返回時,經過map
判斷結果,剔除錯誤信息,成功之後返回到自定義的ProgressSubscriber
對象中,因此接下來封裝ProgressSubscriber
對象。
ProgressSubscriber
封裝ProgressSubscriber
實際上是繼承於Subscriber
,封裝的方法無非是對Subscriber
的回調方法的封裝
http
請求都伴隨着加載框的使用,因此這裏須要在onStart()
使用前初始一個加載框,這裏簡單的用ProgressDialog
代替
/** * 用於在Http請求開始時,自動顯示一個ProgressDialog * 在Http請求結束是,關閉ProgressDialog * 調用者本身對請求數據進行處理 * Created by WZG on 2016/7/16. */
public class ProgressSubscriber<T> extends Subscriber<T> {
/*是否彈框*/
private boolean showPorgress = true;
/* 軟引用回調接口*/
private SoftReference<HttpOnNextListener> mSubscriberOnNextListener;
/*軟引用反正內存泄露*/
private SoftReference<RxAppCompatActivity> mActivity;
/*加載框可本身定義*/
private ProgressDialog pd;
/*請求數據*/
private BaseApi api;
/** * 構造 * * @param api */
public ProgressSubscriber(BaseApi api) {
this.api = api;
this.mSubscriberOnNextListener = api.getListener();
this.mActivity = new SoftReference<>(api.getRxAppCompatActivity());
setShowPorgress(api.isShowProgress());
if (api.isShowProgress()) {
initProgressDialog(api.isCancel());
}
}
/** * 初始化加載框 */
private void initProgressDialog(boolean cancel) {
Context context = mActivity.get();
if (pd == null && context != null) {
pd = new ProgressDialog(context);
pd.setCancelable(cancel);
if (cancel) {
pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
onCancelProgress();
}
});
}
}
}
/** * 顯示加載框 */
private void showProgressDialog() {
if (!isShowPorgress()) return;
Context context = mActivity.get();
if (pd == null || context == null) return;
if (!pd.isShowing()) {
pd.show();
}
}
/** * 隱藏 */
private void dismissProgressDialog() {
if (!isShowPorgress()) return;
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
}
}複製代碼
因爲progress
的特殊性,須要指定content
並且不能是Application
因此這裏傳遞一個RxAppCompatActivity
,而同時上面的HttpManager
一樣須要,因此這裏統一仍是按照BaseApi
傳遞過來,使用軟引用的方式避免泄露。剩下的無非是初始化,顯示和關閉方法,能夠詳細看代碼。
onStart()
實現在onStart()
中須要調用加載框,而後這裏還有網絡緩存的邏輯,後面會單獨講解,如今先忽略它的存在。
/** * 訂閱開始時調用 * 顯示ProgressDialog */
@Override
public void onStart() {
showProgressDialog();
/*緩存而且有網*/
if (api.isCache() && AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) {
/*獲取緩存數據*/
CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
if (cookieResulte != null) {
long time = (System.currentTimeMillis() - cookieResulte.getTime()) / 1000;
if (time < api.getCookieNetWorkTime()) {
if (mSubscriberOnNextListener.get() != null) {
mSubscriberOnNextListener.get().onCacheNext(cookieResulte.getResulte());
}
onCompleted();
unsubscribe();
}
}
}
}複製代碼
/** * 完成,隱藏ProgressDialog */
@Override
public void onCompleted() {
dismissProgressDialog();
}複製代碼
在onError(Throwable e)
是對錯誤信息的處理和緩存讀取的處理,後續會講解,先忽略。
/** * 對錯誤進行統一處理 * 隱藏ProgressDialog * * @param e */
@Override
public void onError(Throwable e) {
dismissProgressDialog();
/*須要緩存而且本地有緩存才返回*/
if (api.isCache()) {
Observable.just(api.getUrl()).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
errorDo(e);
}
@Override
public void onNext(String s) {
/*獲取緩存數據*/
CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(s);
if (cookieResulte == null) {
throw new HttpTimeException("網絡錯誤");
}
long time = (System.currentTimeMillis() - cookieResulte.getTime()) / 1000;
if (time < api.getCookieNoNetWorkTime()) {
if (mSubscriberOnNextListener.get() != null) {
mSubscriberOnNextListener.get().onCacheNext(cookieResulte.getResulte());
}
} else {
CookieDbUtil.getInstance().deleteCookie(cookieResulte);
throw new HttpTimeException("網絡錯誤");
}
}
});
} else {
errorDo(e);
}
}
/*錯誤統一處理*/
private void errorDo(Throwable e) {
Context context = mActivity.get();
if (context == null) return;
if (e instanceof SocketTimeoutException) {
Toast.makeText(context, "網絡中斷,請檢查您的網絡狀態", Toast.LENGTH_SHORT).show();
} else if (e instanceof ConnectException) {
Toast.makeText(context, "網絡中斷,請檢查您的網絡狀態", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "錯誤" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
if (mSubscriberOnNextListener.get() != null) {
mSubscriberOnNextListener.get().onError(e);
}
}複製代碼
onNext(T t)
實現/** * 將onNext方法中的返回結果交給Activity或Fragment本身處理 * * @param t 建立Subscriber時的泛型類型 */
@Override
public void onNext(T t) {
if (mSubscriberOnNextListener.get() != null) {
mSubscriberOnNextListener.get().onNext(t);
}
}複製代碼
主要是是將獲得的結果,經過自定義的接口返回給view
界面,其中的軟引用對象mSubscriberOnNextListener
是自定義的接口回調類HttpOnNextListener
.
HttpOnNextListener
封裝如今只需關心onNext(T t)
和onError(Throwable e)
接口便可,回調的觸發點都是在上面的ProgressSubscriber
中調用
/** * 成功回調處理 * Created by WZG on 2016/7/16. */
public abstract class HttpOnNextListener<T> {
/** * 成功後回調方法 * @param t */
public abstract void onNext(T t);
/** * 緩存回調結果 * @param string */
public void onCacheNext(String string){
}
/** * 失敗或者錯誤方法 * 主動調用,更加靈活 * @param e */
public void onError(Throwable e){
}
/** * 取消回調 */
public void onCancel(){
}
}複製代碼
retry
處理這裏你可能會問,Retrofit
有自帶的retry
處理呀,的確Retrofit
有自帶的retry
處理,可是有不少的侷限,先看下使用
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.retryOnConnectionFailure(true);複製代碼
使用起來仍是很方便,只須要調用一個方法便可,可是它是不可控的,也就是沒有辦法設置retry
時間次數,因此不太靈活,既然如此還不如本身封裝一下,由於用RxJava
實現這個簡直小菜,無形中好像已經給RxJava
打了廣告,中毒太深。
很簡單直接上代碼:
/** * retry條件 * Created by WZG on 2016/10/17. */
public class RetryWhenNetworkException implements Func1<Observable<? extends Throwable>, Observable<?>> {
// retry次數
private int count = 3;
// 延遲
private long delay = 3000;
// 疊加延遲
private long increaseDelay = 3000;
public RetryWhenNetworkException() {
}
public RetryWhenNetworkException(int count, long delay) {
this.count = count;
this.delay = delay;
}
public RetryWhenNetworkException(int count, long delay, long increaseDelay) {
this.count = count;
this.delay = delay;
this.increaseDelay = increaseDelay;
}
@Override
public Observable<?> call(Observable<? extends Throwable> observable) {
return observable
.zipWith(Observable.range(1, count + 1), new Func2<Throwable, Integer, Wrapper>() {
@Override
public Wrapper call(Throwable throwable, Integer integer) {
return new Wrapper(throwable, integer);
}
}).flatMap(new Func1<Wrapper, Observable<?>>() {
@Override
public Observable<?> call(Wrapper wrapper) {
if ((wrapper.throwable instanceof ConnectException
|| wrapper.throwable instanceof SocketTimeoutException
|| wrapper.throwable instanceof TimeoutException)
&& wrapper.index < count + 1) { //若是超出重試次數也拋出錯誤,不然默認是會進入onCompleted
return Observable.timer(delay + (wrapper.index - 1) * increaseDelay, TimeUnit.MILLISECONDS);
}
return Observable.error(wrapper.throwable);
}
});
}
private class Wrapper {
private int index;
private Throwable throwable;
public Wrapper(Throwable throwable, int index) {
this.index = index;
this.throwable = throwable;
}
}
}複製代碼
到這裏,咱們第一步封裝已經完成了,下面講解下如何使用,已經看明白的各位看官,估計早就看明白了使用方式,無非是建立一個api
對象繼承BaseApi
初始接口信息,而後調用HttpManager
對象的doHttpDeal(BaseApi basePar)
方法,最後靜靜的等待回調類HttpOnNextListener<T>
類返回的onNext(T t)
成功數據或者onError(Throwable e)
數據。
其實代碼就是這樣:
api
接口對象/** * 測試數據 * Created by WZG on 2016/7/16. */
public class SubjectPostApi extends BaseApi {
// 接口須要傳入的參數 可自定義不一樣類型
private boolean all;
/*任何你先要傳遞的參數*/
// String xxxxx;
/** * 默認初始化須要給定回調和rx週期類 * 能夠額外設置請求設置加載框顯示,回調等(可擴展) * @param listener * @param rxAppCompatActivity */
public SubjectPostApi(HttpOnNextListener listener, RxAppCompatActivity rxAppCompatActivity) {
super(listener,rxAppCompatActivity);
setShowProgress(true);
setCancel(true);
setCache(true);
setMothed("AppFiftyToneGraph/videoLink");
setCookieNetWorkTime(60);
setCookieNoNetWorkTime(24*60*60);
}
public boolean isAll() {
return all;
}
public void setAll(boolean all) {
this.all = all;
}
@Override
public Observable getObservable(Retrofit retrofit) {
HttpPostService service = retrofit.create(HttpPostService.class);
return service.getAllVedioBys(isAll());
}
}複製代碼
// 完美封裝簡化版
private void simpleDo() {
SubjectPostApi postEntity = new SubjectPostApi(simpleOnNextListener,this);
postEntity.setAll(true);
HttpManager manager = HttpManager.getInstance();
manager.doHttpDeal(postEntity);
}
// 回調一一對應
HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<SubjectResulte>>() {
@Override
public void onNext(List<SubjectResulte> subjects) {
tvMsg.setText("網絡返回:\n" + subjects.toString());
}
@Override
public void onCacheNext(String cache) {
/*緩存回調*/
Gson gson=new Gson();
java.lang.reflect.Type type = new TypeToken<BaseResultEntity<List<SubjectResulte>>>() {}.getType();
BaseResultEntity resultEntity= gson.fromJson(cache, type);
tvMsg.setText("緩存返回:\n"+resultEntity.getData().toString() );
}
/*用戶主動調用,默認是不須要覆寫該方法*/
@Override
public void onError(Throwable e) {
super.onError(e);
tvMsg.setText("失敗:\n" + e.toString());
}
/*用戶主動調用,默認是不須要覆寫該方法*/
@Override
public void onCancel() {
super.onCancel();
tvMsg.setText("取消請求");
}
};複製代碼
到這裏,封裝功能中不少功能還沒涉及和講解,後續會陸續更新!
先給你們看看爲師的徹底體功能:
1.Retrofit+Rxjava+okhttp基本使用方法
2.統一處理請求數據格式
3.統一的ProgressDialog和回調Subscriber處理
4.取消http請求
5.預處理http請求
6.返回數據的統一判斷
7.失敗後的retry處理
8.RxLifecycle管理生命週期,防止泄露
9.文件上傳下載(支持多文件,斷點續傳)
10.Cache數據持久化和數據庫(greenDao)兩種緩存機制
11.異常統一處理複製代碼
來個圖壓壓驚:
火燒眉毛的小夥伴能夠看這裏:
可是其中有些後續優化迭代未及時更新,別生氣,我立刻補!
這篇文章參加掘金技術徵文:gold.xitu.io/post/58522d…