RxRetrofit - 終極封裝 - 深刻淺出 & 異常

背景

在前面Rxjava+ReTrofit+okHttp深刻淺出-終極封裝專欄咱們已經全面的封裝了一套能夠投入實戰的框架,最近QQ羣中有兄弟說異常處理這塊能夠優化優化並給出了建議參考項目,果斷從新將以前的封裝完善走起來,將請求過程當中的處理統一封裝起來,回調給調用者,根據自定義回調類型方便查詢錯誤類型和信息。html


前提

本章的內容基於掌握了前面封裝的原理之後,學期起來才能徹底的理解java

Rxjava+ReTrofit+okHttp深刻淺出-終極封裝專欄git


效果:

這裏寫圖片描述

經過統一的異常處理,能夠實現各類異常的統一處理,而後經過統一回調給使用者,方便統一展現和顯示提示給用戶github

  • 第一條錯誤:故意修改了service裏面方法地址,致使錯誤json

  • 第二條錯誤:過時token,服務器返回的錯誤信息api


優化之路

1.定義回調異常類

定義的回調類,方便回調接口統一處理,其中包含錯誤code和錯誤信息displayMessage緩存

public class ApiException extends Exception{
    /*錯誤碼*/
    private int code;
    /*顯示的信息*/
    private String displayMessage;

    public ApiException(Throwable e) {
        super(e);
    }

    public ApiException(Throwable cause,@CodeException.CodeEp int code, String showMsg) {
        super(showMsg, cause);
        setCode(code);
        setDisplayMessage(showMsg);
    }

    @CodeException.CodeEp public int getCode() {
        return code;
    }

    public void setCode(@CodeException.CodeEp int code) {
        this.code = code;
    }

    public String getDisplayMessage() {
        return displayMessage;
    }

    public void setDisplayMessage(String displayMessage) {
        this.displayMessage = displayMessage;
    }
}複製代碼

2.定義錯誤碼

自定義錯誤碼,相關的錯誤碼能夠自行設定規則,框架如今給出了經常使用的錯誤碼定義,採用上一章講解的Android註解方式來定義錯誤碼的使用:服務器

public class CodeException {

    /*網絡錯誤*/
    public static final int NETWORD_ERROR = 0x1;
    /*http_錯誤*/
    public static final int HTTP_ERROR = 0x2;
    /*fastjson錯誤*/
    public static final int JSON_ERROR = 0x3;
    /*未知錯誤*/
    public static final int UNKNOWN_ERROR = 0x4;
    /*運行時異常-包含自定義異常*/
    public static final int RUNTIME_ERROR = 0x5;
    /*沒法解析該域名*/
    public static final int UNKOWNHOST_ERROR = 0x6;


    @IntDef({NETWORD_ERROR, HTTP_ERROR, RUNTIME_ERROR, UNKNOWN_ERROR, JSON_ERROR, UNKOWNHOST_ERROR})
    @Retention(RetentionPolicy.SOURCE)

    public @interface CodeEp {
    }

}複製代碼

由於是在Rxjava+ReTrofit+okHttp深刻淺出-終極封裝六特殊篇(變種String替換Gson自由擴展)基礎上完善的異常處理,這裏解析使用的是 fastjson的異常定義json解析異常網絡

3.完善自定義運行時異常

HttpTimeException類在以前的封裝中就已經存在,經過它在處理服務器返回錯誤信息和緩存錯誤信息,因此咱們只是完善它的調用規則,讓它更加合理框架

public class HttpTimeException extends RuntimeException {
    /*未知錯誤*/
    public static final int UNKOWN_ERROR = 0x1002;
    /*本地無緩存錯誤*/
    public static final int NO_CHACHE_ERROR = 0x1003;
    /*緩存過期錯誤*/
    public static final int CHACHE_TIMEOUT_ERROR = 0x1004;


    public HttpTimeException(int resultCode) {
        this(getApiExceptionMessage(resultCode));
    }

    public HttpTimeException(String detailMessage) {
        super(detailMessage);
    }

    /** * 轉換錯誤數據 * * @param code * @return */
    private static String getApiExceptionMessage(int code) {
        switch (code) {
            case UNKOWN_ERROR:
                return "錯誤:網絡錯誤";
            case NO_CHACHE_ERROR:
                return "錯誤:無緩存數據";
            case CHACHE_TIMEOUT_ERROR:
                return "錯誤:緩存數據過時";
            default:
                return "錯誤:未知錯誤";
        }
    }
}複製代碼

完善後:加入code碼和對應的錯誤信息

4.創建異常工廠類

異常工廠類中,經過傳入對應的Throwable錯誤,而後根據Throwable的不一樣類型,生成不一樣的與之對應的ApiException異常,最後將ApiException異常返回給最後的rx回調onerror方法,最後onerror方法統一對異常進行處理(若是你的需求又這樣的要求)回調給用戶界面;

public class FactoryException {
    private static final String HttpException_MSG = "網絡錯誤";
    private static final String ConnectException_MSG = "鏈接失敗";
    private static final String JSONException_MSG = "fastjeson解析失敗";
    private static final String UnknownHostException_MSG = "沒法解析該域名";

    /** * 解析異常 * * @param e * @return */
    public static ApiException analysisExcetpion(Throwable e) {
        ApiException apiException = new ApiException(e);
        if (e instanceof HttpException) {
             /*網絡異常*/
            apiException.setCode(CodeException.HTTP_ERROR);
            apiException.setDisplayMessage(HttpException_MSG);
        } else if (e instanceof HttpTimeException) {
             /*自定義運行時異常*/
            HttpTimeException exception = (HttpTimeException) e;
            apiException.setCode(CodeException.RUNTIME_ERROR);
            apiException.setDisplayMessage(exception.getMessage());
        } else if (e instanceof ConnectException||e instanceof SocketTimeoutException) {
             /*連接異常*/
            apiException.setCode(CodeException.HTTP_ERROR);
            apiException.setDisplayMessage(ConnectException_MSG);
        } else if (e instanceof JSONPathException || e instanceof JSONException || e instanceof ParseException) {
             /*fastjson解析異常*/
            apiException.setCode(CodeException.JSON_ERROR);
            apiException.setDisplayMessage(JSONException_MSG);
        }else if (e instanceof UnknownHostException){
            /*沒法解析該域名異常*/
            apiException.setCode(CodeException.UNKOWNHOST_ERROR);
            apiException.setDisplayMessage(UnknownHostException_MSG);
        } else {
            /*未知異常*/
            apiException.setCode(CodeException.UNKNOWN_ERROR);
            apiException.setDisplayMessage(e.getMessage());
        }
        return apiException;
    }
}複製代碼

這個異常工廠類中的異常判斷在實際開發中,能夠動態的本身添加,能夠將分類更加細化完善!

5.rx錯誤異常的轉換

rx在連接調用過程當中產生的異常默認是經過Subscriber的onError(Throwable e)方法回調,這裏咱們須要將Throwable 轉換成自定義ApiException回調,因此須要調用rxjava中的onErrorResumeNext方法,在異常回調前經過異常工廠類FactoryException處理返回統一的ApiException

僞代碼

****
******
********
 Observable observable = basePar.getObservable(httpService)
                /*失敗後的retry配置*/
                .retryWhen(new RetryWhenNetworkException())
                /*異常處理*/
                .onErrorResumeNext(funcException)

**********

  /** * 異常處理 */
    Func1 funcException = new Func1<Throwable, Observable>() {
        @Override
        public Observable call(Throwable throwable) {
            return Observable.error(FactoryException.analysisExcetpion(throwable));
        }
    };複製代碼

6.回調結果的統一處理

  • 1.由於改成統一的錯誤毀掉類型,須要修改以前的回到接口類
/** * 成功回調處理 * Created by WZG on 2016/7/16. */
public interface HttpOnNextListener {
    /** * 成功後回調方法 * @param resulte * @param mothead */
   void onNext(String resulte,String mothead);

    /** * 失敗 * 失敗或者錯誤方法 * 自定義異常處理 * @param e */
    void onError(ApiException e);
}複製代碼
  • 2.onError(Throwable e)回調處理
/** * 錯誤統一處理 * * @param e */
    private void errorDo(Throwable e) {
        Context context = mActivity.get();
        if (context == null) return;
        HttpOnNextListener httpOnNextListener = mSubscriberOnNextListener.get();
        if (httpOnNextListener == null) return;
        if (e instanceof ApiException) {
            httpOnNextListener.onError((ApiException) e);
        } else if (e instanceof HttpTimeException) {
            HttpTimeException exception=(HttpTimeException)e;
            httpOnNextListener.onError(new ApiException(exception,CodeException.RUNTIME_ERROR,exception.getMessage()));
        } else {
            httpOnNextListener.onError(new ApiException(e, CodeException.UNKNOWN_ERROR,e.getMessage()));
        }
        /*能夠在這裏統一處理錯誤處理-可自由擴展*/
        Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
    }複製代碼

這裏能夠統一對異常進行統一處理,默認如今是toast提示,固然也有回調的傳遞

  • 3.顯示界面
@Override
    public void onNext(String resulte, String mothead) {
       *****
    }

    @Override
    public void onError(ApiException e) {
        tvMsg.setText("失敗:\ncode=" + e.getCode()+"\nmsg:"+e.getDisplayMessage());
    }複製代碼

最後統一回調在onError中傳遞迴一個ApiException對象


終極封裝專欄

RxJava+Retrofit+OkHttp深刻淺出-終極封裝專欄)


項目地址

傳送門-GitHub-戳我


建議

若是你對這套封裝有任何的問題和建議歡迎加入QQ羣告訴我!

相關文章
相關標籤/搜索