1. 程式人生 > >Retrofit2和Rxjava2封裝思路

Retrofit2和Rxjava2封裝思路

//ApiService.java
public interface ApiService {


  @POST("app/api")
    Observable<Response2> request2(@Body Request2 request);
    /**
     * Create a new ApiService
     */
    class Factory {
        private Factory() {  }

        public static ApiService createService( ) {
            OkHttpClient
.Builder builder = new OkHttpClient().newBuilder(); builder.readTimeout(10, TimeUnit.SECONDS); builder.connectTimeout(9, TimeUnit.SECONDS); if (BuildConfig.DEBUG) { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor
.Level.BODY)
; builder.addInterceptor(interceptor); } builder.addInterceptor(new HeaderInterceptor()); OkHttpClient client = builder.build(); Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiService.ENDPOINT) .client(client
)
.addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); return retrofit.create(ApiService.class); } } }

使用起來如下

ApiService mApiService = ApiService.Factory.createService();
mApiService.request1(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Response1>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Response1 response) {
                        int code = response.getCode();
                        switch (code) {
                            case 1: //do something
                                break;
                            case -101://do something
                                break;
                            case -102: //do something
                                break;
                            default:
                                break;
                        }
                    }
                });

最終目標封裝成如下

    @POST("order/getAllOrders")
    Observable<HttpResult<List<Order>>> postOrderList(@Body OrderRequest request);
           ServiceFactory.orderApi()
                    .postOrderListState(mRequest)
                    .compose(new DefaultTransformer<List<Order>>())
                    .subscribe(new CommonSubscriber<List<Order>>(mContext) {
                        @Override
                        public void onNext(List<Order> data) {


                        }

                        @Override
                        protected void onError(ApiException ex) {
                            super.onError(ex);
                            ToastUtil.showShort(mContext, ex.message);
                        }
                    });

提取ApiService的Api類的建立
上面的Factory一起建立一個ServiceFactory

這裡寫圖片描述

  //https 支援
  HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
        sClient = new OkHttpClient().newBuilder()
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                //設定連結時間
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                //設定攔截器
                .addInterceptor(new HeaderInterceptor())
                .addInterceptor(new TokenInterceptor())
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
                .retryOnConnectionFailure(true)
                //斷網重連
                .build();
        OkHttpUtils.initClient(sClient);

        sRetrefit = new Retrofit.Builder()
                .client(sClient)
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(MyApplication.getmGson()))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

DefaultTransformer封裝
首先得了解操作符compose()和flatMap()有啥區別呢。他們都是發射出Observable,是不是就是說他們都可以複用一系列操作符呢?

compose() 是針對 Observable 自身進行變換。

  1. compose()是唯一一個能從流中獲取原生Observable
    的方法,因此,影響整個流的操作符(像subscribeOn()和observeOn())需要使用compose(),相對的,如果你在flatMap()中使用subscribeOn()/observeOn(),它隻影響你建立的flatMap()中的Observable,而不是整個流。

  2. 當你建立一個Observable流並且內聯了一堆操作符以後,compose()會立即執行,flatMap()則是在onNext()被呼叫以後才會執行,換句話說,flatMap()轉換的是每個專案,而compose()轉換的是整個流。

  3. flatMap()一定是低效率的,因為他每次呼叫onNext()之後都需要建立一個新的Observable,compose()是操作在整個流上的。
    這裡寫圖片描述
    這裡寫圖片描述

這裡沒有出錯就轉成HttpResult出錯了就丟擲異常

                // 通過對返回碼進行業務判斷決定是返回錯誤還是正常取資料    
               if (httpResult.getCode() != ErrorType.SUCCESS) {
                    throw new ServerException(httpResult.getMessage(), httpResult.getCode());
                }
                return httpResult.getData();
 .onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() {
            @Override
            public Observable<? extends T> call(Throwable throwable) {
                //ExceptionEngine為處理異常的驅動器
                return Observable.error(ExceptionEngine.handleException(throwable));
            }
        });

丟擲異常以後再走.onErrorResumeNext 方法

public class ServerException extends RuntimeException {
    // 異常處理,為速度,不必要設定getter和setter
    public int code;
    public String message;

    public ServerException(String message, int code) {
        super(message);
        this.code = code;
        this.message = message;
    }
}
public class ExceptionEngine {
    //對應HTTP的狀態碼
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;

    public static ApiException handleException(Throwable e) {
        ApiException ex;
        if (e instanceof HttpException) {             //HTTP錯誤
            HttpException httpException = (HttpException) e;
            ex = new ApiException(e, ErrorType.HTTP_ERROR);
            switch (httpException.code()) {
                case UNAUTHORIZED:
                    ex.message = "當前請求需要使用者驗證";
                    break;
                case FORBIDDEN:
                    ex.message = "伺服器已經理解請求,但是拒絕執行它";
                    break;
                case NOT_FOUND:
                    ex.message = "伺服器異常,請稍後再試";
                    break;
                case REQUEST_TIMEOUT:
                    ex.message = "請求超時";
                    break;
                case GATEWAY_TIMEOUT:
                    ex.message = "作為閘道器或者代理工作的伺服器嘗試執行請求時,未能及時從上游伺服器(URI標識出的伺服器,例如HTTP、FTP、LDAP)或者輔助伺服器(例如DNS)收到響應";
                    break;
                case INTERNAL_SERVER_ERROR:
                    ex.message = "伺服器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理";
                    break;
                case BAD_GATEWAY:
                    ex.message = "作為閘道器或者代理工作的伺服器嘗試執行請求時,從上游伺服器接收到無效的響應";
                    break;
                case SERVICE_UNAVAILABLE:
                    ex.message = "由於臨時的伺服器維護或者過載,伺服器當前無法處理請求";
                    break;

                default:
                    ex.message = "網路錯誤";  //其它均視為網路錯誤
                    break;
            }
            return ex;
        } else if (e instanceof ServerException) {    //伺服器返回的錯誤
            ServerException resultException = (ServerException) e;
            ex = new ApiException(resultException, resultException.code);
            ex.message = resultException.message;
            return ex;
        } else if (e instanceof JsonSyntaxException) {
//            ex = new ApiException(e, ErrorType.TOKEN_INVALID);
//            ex.message = "Token失效";            //均視為解析錯誤
            ex = new ApiException(e, ErrorType.PARSE_ERROR);
            ex.message = "返回資料錯誤";            //均視為解析錯誤
            return ex;
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            ex = new ApiException(e, ErrorType.PARSE_ERROR);
            ex.message = "解析錯誤";            //均視為解析錯誤
            return ex;
        } else if (e instanceof ConnectException || e instanceof SocketTimeoutException || e instanceof ConnectTimeoutException) {
            ex = new ApiException(e, ErrorType.NETWORD_ERROR);
            ex.message = "連線失敗";  //均視為網路錯誤
            return ex;
        } else {
            ex = new ApiException(e, ErrorType.UNKNOWN);
            ex.message = "未知錯誤";          //未知錯誤
            return ex;
        }
    }

最後再走CommonSubscriber.error