Android RxJava+Retrofit網路異常、狀態代碼統一處理__Java

來源:互聯網
上載者:User
Android RxJava+Retrofit 網路異常捕獲、狀態代碼統一處理 前言

近來使用RxJava+Retrofit進行開發,在項目中遇到這樣一個需求,連網請求獲得資料異常時,需要將對應的Message和StatusCode進行獲得並展示,比如:
1.伺服器串連Error: 對應的返回404,500等等;
2.沒有網路狀態(沒有4g,3g,是否處於wifi環境下等);

參考文章:
Rxjava +Retrofit 你需要掌握的幾個技巧,Retrofit緩衝,RxJava封裝,統一對有無網路處理,異常處理, 返回結果問題 @碼小白 一、簡單的擷取處理

最簡單的處理方式,直接對返回的throwable進行類型判斷處理:

//先判斷網路環境if(!NetUtils.is4G(context)){    return;}//再連網請求,對throwable進行判斷ServiceHelper.getInstance()          .getModelResult(param1, param2)          .subscribeOn(Schedulers.io())          .observeOn(AndroidSchedulers.mainThread())          .subscribe(new Subscriber<Model>() {                 @Override                  public void onCompleted() {                  }                  @Override                  public void onError(Throwable e) {                      if(e instanceof HttpException){                          //擷取對應statusCode和Message                          HttpException exception = (HttpException)e;                          String message = exception.response().message();                          int code = exception.response().code();                      }else if(e instanceof SSLHandshakeException){                        //接下來就是各種異常類型判斷...                      }else if(e instanceof ...){                      }...                       ...                  }                  @Override                  public void onNext(Model model) {                  }          });

顯然,代碼並不難以理解,但是非常麻煩,總不至於每次都要進行這樣的大塊代碼複製粘貼吧。
請注意,進行類型判斷的的HttpException為

import retrofit2.adapter.rxjava.HttpException;

所以需要我們依賴:

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
二、NetErrorUtil封裝 1.首先我們建立一個Throwable的管理類
public class ExceptionHandle {    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 ResponeThrowable handleException(Throwable e) {        ResponeThrowable ex;        Log.i("tag", "e.toString = " + e.toString());        if (e instanceof HttpException) {            HttpException httpException = (HttpException) e;            ex = new ResponeThrowable(e, ERROR.HTTP_ERROR);            switch (httpException.code()) {                case UNAUTHORIZED:                case FORBIDDEN:                case NOT_FOUND:                case REQUEST_TIMEOUT:                case GATEWAY_TIMEOUT:                case INTERNAL_SERVER_ERROR:                case BAD_GATEWAY:                case SERVICE_UNAVAILABLE:                default:                    //ex.code = httpException.code();                    ex.message = "網路錯誤";                    break;            }            return ex;        } else if (e instanceof ServerException) {            ServerException resultException = (ServerException) e;            ex = new ResponeThrowable(resultException, resultException.code);            ex.message = resultException.message;            return ex;        } else if (e instanceof JsonParseException                || e instanceof JSONException                /*|| e instanceof ParseException*/) {            ex = new ResponeThrowable(e, ERROR.PARSE_ERROR);            ex.message = "解析錯誤";            return ex;        } else if (e instanceof ConnectException) {            ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR);            ex.message = "串連失敗";            return ex;        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {            ex = new ResponeThrowable(e, ERROR.SSL_ERROR);            ex.message = "認證驗證失敗";            return ex;        } else {            ex = new ResponeThrowable(e, ERROR.UNKNOWN);            ex.message = "未知錯誤";            return ex;        }    }    /**     * 約定異常     */    class ERROR {        /**         * 未知錯誤         */        public static final int UNKNOWN = 1000;        /**         * 解析錯誤         */        public static final int PARSE_ERROR = 1001;        /**         * 網路錯誤         */        public static final int NETWORD_ERROR = 1002;        /**         * 協議出錯         */        public static final int HTTP_ERROR = 1003;        /**         * 認證出錯         */        public static final int SSL_ERROR = 1005;    }    public static class ResponeThrowable extends Exception {        public int code;        public String message;        public ResponeThrowable(Throwable throwable, int code) {            super(throwable);            this.code = code;        }    }    /**     * ServerException發生後,將自動轉換為ResponeThrowable返回     */    class ServerException extends RuntimeException {        int code;        String message;    }}

在這個類中,我們把throwable進行類型統一判斷:
1.若為Exception,我們再進行判斷,根據不同種類的Exception,轉化為ResponeThrowable返回,並賦予不同的code和message;
2.若為RuntimeException,我們再轉換為ResponeThrowable返回; 總而言之,我們把擷取到的異常,通過handleException()方法,轉化為統一的ResponeThrowable返回,這個對象包含code和message。 2.然後是建立一個新的Subscriber基類

/** * Subscriber基類,可以在這裡處理client網路連接狀況 * (比如沒有wifi,沒有4g,沒有連網等) * Created by fcn-mq on 2017/4/19. */public abstract class MySubscriber<T> extends Subscriber<T> {    private Context context;    public MySubscriber(Context context) {        this.context = context;    }    @Override    public void onStart() {        super.onStart();        Log.i("tag","MySubscriber.onStart()");        //接下來可以檢查網路連接等操作        if (!NetworkUtil.isNetworkAvailable(context)) {            Toast.makeText(context, "當前網路不可用,請檢查網路情況", Toast.LENGTH_SHORT).show();            // 一定好主動調用下面這一句,取消本次Subscriber訂閱            if (!isUnsubscribed()) {                unsubscribe();            }            return;        }    }    @Override    public void onError(Throwable e) {        Log.e("tag","MySubscriber.throwable ="+e.toString());        Log.e("tag","MySubscriber.throwable ="+e.getMessage());        if(e instanceof Exception){            //訪問獲得對應的Exception            onError(ExceptionHandle.handleException(e));        }else {            //將Throwable 和 未知錯誤的status code返回            onError(new ExceptionHandle.ResponeThrowable(e,ExceptionHandle.ERROR.UNKNOWN));        }    }    public abstract void onError(ExceptionHandle.ResponeThrowable responeThrowable);    @Override    public void onCompleted() {        Log.i("tag","MySubscriber.onComplete()");    }}

這個就好理解了,我們可以在基類中統一進行用戶端網路環境的判斷,或者當網路異常發生時,統一轉換為
ResponeThrowable,在onError(ExceptionHandle.ResponeThrowable responeThrowable)中回調,這個abstract的回調方法需要我們自己實現。 3.代碼中使用:

new Retrofit.Builder()            .baseUrl(ConstantsApi.BASE_DOUBAN)             .addConverterFactory(GsonConverterFactory.create())             .addCallAdapterFactory(RxJavaCallAdapterFactory.create())             .client(client)             .build()             .create(DoubanMovieService.class)//獲得對應的service對象             .getModelResult(param1, param2)  //網路請求             .subscribeOn(Schedulers.io())             .observeOn(AndroidSchedulers.mainThread())             .subscribe(new MySubscriber<Model>(context) {                 @Override                 public void onNext(Model model) {                   ...                 }                 @Override                 public void onError(ExceptionHandle.ResponeThrowable throwable) {                     LogUtil.m("tag","throwable =" + throwable.toString());                     //接下來就可以根據狀態代碼進行處理...                     int statusCode = throwable.code;                     switch (statusCode){                         case ExceptionHandle.ERROR.SSL_ERROR:                          break;                         case ExceptionHandle.ERROR.UNKNOWN:                          break;                         case ExceptionHandle.ERROR.PARSE_ERROR:                          break;                         case ExceptionHandle.ERROR.NETWORD_ERROR:                             break;                         case ExceptionHandle.ERROR.HTTP_ERROR:                       break;                     }                 }             });

最後是NetErrorUtil的源碼地址:點我點我

【GitHub地址】https://github.com/ButQingMei/Samples.git

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.