免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
一步一步帶你認(rèn)識(shí) MVP+Retrofit+Rxjava 并封裝(二)

序言

繼續(xù)上周咱們沒(méi)講完的,上周咱們一起擼了一把 MVP,今天跟著LZ繼續(xù)擼Retrofit+RxJava,這倆算得上當(dāng)下最流行的網(wǎng)絡(luò)框架了,數(shù)據(jù)說(shuō)話,有空的話你們也去 github 上搜索一波:

我們可以看出來(lái),單論 star 數(shù)的話,Retrofit 和 OkHttp 是巨頭般的存在,網(wǎng)上關(guān)于 retrofit 的文章早已數(shù)不勝數(shù)了,這里我也不詳細(xì)介紹了,下面就直接進(jìn)入主題。

封裝

在開(kāi)始之前,先介紹大家去學(xué)習(xí)一下 RxJava,這個(gè)是真的灰常有用的一個(gè)庫(kù),Rx 系列的都很不錯(cuò),這里有兩個(gè)版本,他們之間的方法稍微改變了一下,其他都差不多:

給初學(xué)者的 RxJava2.0 教程系列 

http://www.jianshu.com/u/c50b715ccaeb

給 Android 開(kāi)發(fā)者的 RxJava1.0 詳解 

http://gank.io/post/560e15be2dca930e00da1083

如果你上周沒(méi)跟著LZ一起擼的話,那么請(qǐng)移步:
一步一步帶你認(rèn)識(shí) MVP+Retrofit+Rxjava 并封裝(一)

1、導(dǎo)包:

2、封裝:

我們先來(lái)看一下,一個(gè)完整的 Retrofit+Rxjva 的請(qǐng)求:

OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
builder.connectTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
//設(shè)置攔截器
builder.addInterceptor(new BasicParamsInterceptor.Builder().addParamsMap(getCommonMap()).build());
builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
OkHttpClient okHttpClient = builder.build();
Retrofit retrofit = new Retrofit.Builder()
       .baseUrl(BASE_URL)
       .client(okHttpClient)
       .addConverterFactory(CustomGsonConverterFactory.create())
       .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
       .build();
ApiService api=retrofit.create(ApiService.class);

api.login(username,password)
  .subscribeOn(Schedulers.io())               //在IO線程進(jìn)行網(wǎng)絡(luò)請(qǐng)求
  .observeOn(AndroidSchedulers.mainThread())  //回到主線程去處理請(qǐng)求結(jié)果
  .subscribe(new Observer<LoginResponse>() {
      @Override
      public void onSubscribe(Disposable d) {
              //為請(qǐng)求提供一個(gè)取消的手段
      }

      @Override
      public void onNext(LoginResponse value) {
              //請(qǐng)求成功
      }

      @Override
      public void onError(Throwable e) {
          //請(qǐng)求出錯(cuò)
      }

      @Override
      public void onComplete() {
          //請(qǐng)求完成
      }
  });

考慮到每次請(qǐng)求接口的時(shí)候都需要去實(shí)例化一個(gè) Retrofit 對(duì)象,而且每次都需要用 RxJava 來(lái)進(jìn)行線程的切換,因此我就想到把它們都寫(xiě)到一個(gè)基類(lèi)里面去。

public abstract class BaseRetrofit {

   protected Retrofit mRetrofit;
   private static final int DEFAULT_TIME = 10;    //默認(rèn)超時(shí)時(shí)間
   private final long RETRY_TIMES = 1;   //重訂閱次數(shù)
   public BaseRetrofit() {
       //創(chuàng)建okHttpClient
       if (null == mRetrofit) {
           OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
           builder.readTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
           builder.connectTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
           //設(shè)置攔截器
           builder.addInterceptor(new BasicParamsInterceptor.Builder().addParamsMap(getCommonMap()).build());
           builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
           OkHttpClient okHttpClient = builder.build();
           mRetrofit = new Retrofit.Builder()
                   .baseUrl(HttpServletAddress.getInstance().getServletAddress())
                   .client(okHttpClient)
                   .addConverterFactory(CustomGsonConverterFactory.create())
                   .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                   .build();
       }
   }
}

然后結(jié)合我們上周講的 MVP,讓 BaseModel 繼承它,然后調(diào)用方法進(jìn)行請(qǐng)求,上周我們還沒(méi)有細(xì)節(jié)講它是怎么樣進(jìn)行網(wǎng)絡(luò)請(qǐng)求的,回到剛才那個(gè)完整的請(qǐng)求的例子,可以看到,這里發(fā)起請(qǐng)求需要兩個(gè)東西,一個(gè) Observer,另一個(gè)是 api.login()的返回值 Observable,這就是大佬們口中說(shuō)的觀察者和被觀察者,他們之間有一個(gè)很微妙的關(guān)系,叫訂閱;被觀察者負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求,觀察者負(fù)責(zé)觀察網(wǎng)絡(luò)請(qǐng)求的回調(diào),每發(fā)生一次接口請(qǐng)求,都會(huì)有訂閱發(fā)生,所以在這里我把訂閱公共的邏輯放到了 BaseRetrofit中:

protected <T> void toSubscribe(Observable<T> observable, Observer<T> observer) {
   observable.subscribeOn(Schedulers.io())    // 指定subscribe()發(fā)生在IO線程
           .observeOn(AndroidSchedulers.mainThread())  // 指定Subscriber的回調(diào)發(fā)生在io線程
           .timeout(DEFAULT_TIME, TimeUnit.SECONDS)    //重連間隔時(shí)間
           .retry(RETRY_TIMES)
//          .repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
//                @Override
//                public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
//                    return null;
//                }
//           })
           .subscribe(observer);   //訂閱
}

這樣每次我們組裝好 Observable 和 Observer 之后就調(diào)用這個(gè)方法進(jìn)行訂閱就好了。這里我有一個(gè)困惑,已經(jīng)很久了,希望知道的讀者能幫忙解惑,重寫(xiě) retryWhen 的時(shí)候,如何根據(jù)錯(cuò)誤類(lèi)型進(jìn)行重試。講到這里可能有人就要問(wèn)了,LZ你不還是沒(méi)有講是怎么進(jìn)行網(wǎng)絡(luò)請(qǐng)求的嗎?大兄弟別急,我這就告訴你,它是通過(guò)自定義接口的形式來(lái)進(jìn)行網(wǎng)絡(luò)請(qǐng)求的,好吧,說(shuō)了好像也白說(shuō),換個(gè)場(chǎng)景你自個(gè)去深入了解去吧:
Retrofit 網(wǎng)絡(luò)請(qǐng)求框架的基本使用 http://blog.csdn.net/zw904448290/article/details/52717384


好了,接著我們下面的封裝:

被觀察者已經(jīng)當(dāng)作接口被我們處理掉了,那么下面我們重點(diǎn)關(guān)注觀察者;很久之前我老大跟我講網(wǎng)絡(luò)請(qǐng)求封裝這一塊,他當(dāng)時(shí)說(shuō)我們只關(guān)注請(qǐng)求成功的數(shù)據(jù),其他的不需要特別關(guān)注;首先,我們得有一套統(tǒng)一的回調(diào)樣式,如下:

由于我們這邊都把返回的 json 數(shù)據(jù)都轉(zhuǎn)成 BaseResponse<T>格式了,如果你們回調(diào)的數(shù)據(jù)格式不統(tǒng)一的話,那就去找后端撕逼去吧;然后我們只需要重寫(xiě)Observer 就行了,Observer 接口中有四個(gè)方法,上面例子中我們簡(jiǎn)單介紹了一下,它們的執(zhí)行順序分別是 onSubscribe——>onNext——>onComplete(onError),這里需要簡(jiǎn)單提一下,onComplete 和 onError方法二者不會(huì)同時(shí)都執(zhí)行,具體來(lái)看一下LZ封裝的:

public abstract class BaseObserver<T> implements Observer<T> {

   private static final String TAG = "BaseObserver";

   protected abstract void onBaseError(Throwable t);

   protected abstract void onBaseNext(T data);

   protected abstract boolean isNeedProgressDialog();

   protected abstract String getTitleMsg();

   private ProgressDialogHandler mProgressDialogHandler;
   private BaseImpl mBaseImpl;

   public BaseObserver(BaseImpl baseImpl) {
       mBaseImpl = baseImpl;
       if (null != mBaseImpl) {
           if (null == mProgressDialogHandler) {
               mProgressDialogHandler = new ProgressDialogHandler(baseImpl.getContext(), true);
           }
       }
   }

   private void showProgressDialog() {
       if (mProgressDialogHandler != null) {
           mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG, getTitleMsg()).sendToTarget();
       }
   }

   private void dismissProgressDialog() {
       if (mProgressDialogHandler != null) {
           mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
           mProgressDialogHandler = null;
       }
   }

   @Override
   public void onSubscribe(Disposable d) {
       //顯示進(jìn)度條
       if (isNeedProgressDialog()) {
           showProgressDialog();
       }
       if (null != mBaseImpl) {
           if (null != d) {
               mBaseImpl.addDisposable(d);
           }
       }
   }

   @Override
   public void onNext(T value) {
       //成功
       Log.d(TAG, "http is onNext");
       if (null != value) {
           onBaseNext(value);
       }
   }

   @Override
   public void onError(Throwable e) {
       //關(guān)閉進(jìn)度條
       Log.e(TAG, "http is onError");
       if (isNeedProgressDialog()) {
           dismissProgressDialog();
       }
       onBaseError(e);
   }

   @Override
   public void onComplete() {
       //關(guān)閉進(jìn)度條
       if (isNeedProgressDialog()) {
           dismissProgressDialog();
       }
   }
}

這里考慮到有些界面需要進(jìn)度框,所以我把這一部分也整合到觀察者里面,這里根據(jù)外面調(diào)用的地方有沒(méi)有設(shè)置 Title來(lái)判斷是否顯示進(jìn)度框,然后再進(jìn)行相應(yīng)的回調(diào),進(jìn)度框使用的是系統(tǒng)的 ProgressDialog,當(dāng)然了,你也可以自定義一個(gè)進(jìn)度框樣式,詳細(xì)見(jiàn) demo。前面我們說(shuō)到我們只關(guān)心成功的數(shù)據(jù),失敗的數(shù)據(jù)我們需要在內(nèi)部處理掉,即再封裝一層,吃掉 onBaseError

public abstract class CygBaseObserver<T> extends BaseObserver<T> {

   private static final String TAG = "CygBaseObserver";

   private boolean isNeedProgress;
   private String titleMsg;

   public CygBaseObserver() {
       this(null, null);
   }

   public CygBaseObserver(BaseImpl base) {
       this(base, null);
   }

   public CygBaseObserver(BaseImpl base, String titleMsg) {
       super(base);
       this.titleMsg = titleMsg;
       if (TextUtils.isEmpty(titleMsg)) {
           this.isNeedProgress = false;
       } else {
           this.isNeedProgress = true;
       }
   }

   @Override
   protected boolean isNeedProgressDialog() {
       return isNeedProgress;
   }

   @Override
   protected String getTitleMsg() {
       return titleMsg;
   }

   @Override
   protected void onBaseError(Throwable t) {
       StringBuffer sb = new StringBuffer();
       sb.append("請(qǐng)求失?。?);
       if (t instanceof NetworkErrorException || t instanceof UnknownHostException || t instanceof ConnectException) {
           sb.append("網(wǎng)絡(luò)異常");
       } else if (t instanceof SocketTimeoutException || t instanceof InterruptedIOException || t instanceof TimeoutException) {
           sb.append("請(qǐng)求超時(shí)");
       } else if (t instanceof JsonSyntaxException) {
           sb.append("請(qǐng)求不合法");
       } else if (t instanceof JsonParseException
               || t instanceof JSONException
               || t instanceof ParseException)
{   //  解析錯(cuò)誤
           sb.append("解析錯(cuò)誤");
       } else if (t instanceof ApiException) {
           if (((ApiException) t).isTokenExpried()) {
               sb.append("Token出錯(cuò)");
           }
       } else {
           FRToast.showToastSafe(t.getMessage());
           return;
       }
       Log.e(TAG, "onBaseError: " + sb.toString());
       FRToast.showToastSafe(sb.toString());
   }
}

最開(kāi)始的例子當(dāng)中有一個(gè) Disposable 的概念,這個(gè)是用來(lái)切斷觀察者與被觀察者之間的關(guān)系的,每次請(qǐng)求都會(huì)產(chǎn)生一個(gè)響應(yīng)的 Disposable,所以這里我用了一個(gè)接口 BaseImpl 的形式來(lái)回收它,在產(chǎn)生的地方收集它,在 BaseActivity 的 onDestroy 中來(lái)回收它,詳細(xì)的請(qǐng)參見(jiàn) demo;好了,到這里我們的封裝就完成了 90% 了,讓我們回到上一次博客當(dāng)中,組裝 Observable的時(shí)候我們還進(jìn)行了一個(gè) map 操作:

這里 map 就是進(jìn)行一個(gè)中間的操作,這個(gè)操作叫做變換,我們來(lái)看一下HttpFunction 的實(shí)現(xiàn)是怎樣的:

public class HttpFunction<T> implements Function<BaseResponse<T>, T> {

   @Override
   public T apply(BaseResponse<T> response) throws Exception {
       if (!response.isRequestSuccess()) {
           throw new ApiException(response.getStatus(), String.valueOf(response.getMsg()));
       }
       return response.getData();
   }
}

相信看完方法的實(shí)現(xiàn)大家應(yīng)該知道這個(gè)是干什么用的了,沒(méi)錯(cuò),這個(gè)方法就是將 BaseResponse<T> 轉(zhuǎn)換成 T,因?yàn)槲覀冎魂P(guān)注成功的數(shù)據(jù),而且只關(guān)注data 里面的數(shù)據(jù),由于返回的數(shù)據(jù)是 BaseResponse<T>,而我們需要關(guān)注的數(shù)據(jù)是T,所以在這里需要轉(zhuǎn)換一下,然后判斷請(qǐng)求是否成功就行了。

好了,到這里基本的網(wǎng)絡(luò)請(qǐng)求封裝就完成了,如果你有更好的方法,請(qǐng)私信我一起交流,同時(shí)感謝以上引用到博客的博主。最后的最后,放出最后的代碼,歡迎 star 和 fork

MVP 主工程代碼

https://github.com/Jakemesdg/MVPDemo

MVP module工程代碼

https://github.com/Jakemesdg/cygmodule

與之相關(guān)

一步一步帶你認(rèn)識(shí) MVP+Retrofit+Rxjava 并封裝(一)

關(guān)鍵詞:code小生

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
RxRetrofit 網(wǎng)絡(luò)框架解析
Retrofit結(jié)合RxJava使用指南
RxJava Retrofit OkHttp深入淺出
RxJava 的使用入門(mén)
Android RxJava Retrofit完美封裝
淺談 RxAndroid + Retrofit + Databinding
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服