RxJava+Retrofit+OkHttp深入淺出-終極封裝七(異常處理)
背景
在前面Rxjava+ReTrofit+okHttp深入淺出-終極封裝專欄我們已經全面的封裝了一套可以投入實戰的框架,最近開設了微信群中有兄弟說異常處理這塊可以優化優化並給出了建議參考專案,果斷重新將之前的封裝完善走起來,將請求過程中的處理統一封裝起來,回撥給呼叫者,根據自定義回撥型別方便查詢錯誤型別和資訊。
前提
本章的內容基於掌握了前面封裝的原理以後,學期起來才能完全的理解
效果:
通過統一的異常處理,可以實現各種異常的統一處理,然後通過統一回撥給使用者,方便統一展示和顯示提示給使用者
-
第一條錯誤:故意修改了
service
裡面方法地址,導致錯誤 -
第二條錯誤:過期
token
,伺服器返回的錯誤資訊
優化之路
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
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 {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
因為是在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 "錯誤:未知錯誤";
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
完善後:加入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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
這個異常工廠類中的異常判斷在實際開發中,可以動態的自己新增,可以將分類更加細化完善!
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));
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
這裡可以統一對異常進行統一處理,預設現在是toast
提示,當然也有回撥的傳遞
- 3.顯示介面
@Override
public void onNext(String resulte, String mothead) {
*****
}
@Override
public void onError(ApiException e) {
tvMsg.setText("失敗:\ncode=" + e.getCode()+"\nmsg:"+e.getDisplayMessage());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
最後統一回撥在onError
中傳遞迴一個ApiException
物件
終極封裝專欄
專案地址
建議
相關文章
- RxRetrofit - 終極封裝 - 深入淺出 & 異常封裝
- RxJava+Retrofit+OkHttp 深入淺出-終極封裝一RxJavaHTTP封裝
- RxJava+Retrofit+OkHttp深入淺出-終極封裝三(檔案上傳)RxJavaHTTP封裝
- RxJava+Retrofit+OkHttp深入淺出-終極封裝五(資料持久化)RxJavaHTTP封裝持久化
- RxRetrofit-終極封裝-深入淺出&入門封裝
- RxRetrofit – 終極封裝 – 深入淺出 & 資料快取封裝快取
- RxRetrofit - 終極封裝 - 深入淺出 & 斷點續傳封裝斷點
- RxRetrofit - 終極封裝 - 深入淺出 & 檔案上傳封裝
- RxRetrofit - 終極封裝 - 深入淺出 & 資料快取封裝快取
- RxRetrofit-終極封裝-深入淺出&網路請求封裝
- RxRetrofit - 終極封裝 - 深入淺出 & 擴充套件 String封裝套件
- RxJava+Retrofit+OkHttp深入淺出-終極封裝六特殊篇(變種String替換Gson自由擴充套件)RxJavaHTTP封裝套件
- 深入淺出話異常-(1) (轉)
- RxJava+Retrofit+OkHttp深入淺出-mvp(使用篇)RxJavaHTTPMVP
- 深入理解Spring異常處理Spring
- PHP系列(七)PHP錯誤異常處理PHP
- 異常篇——異常處理
- 深入理解java異常處理機制Java
- Spring系列(七) Spring MVC 異常處理SpringMVC
- 異常處理
- 異常-throws的方式處理異常
- 異常處理與異常函式函式
- JavaScript 異常處理JavaScript
- ThinkPHP 異常處理PHP
- React 異常處理React
- 08、異常處理
- JAVA 異常處理Java
- JAVA異常處理Java
- Abp 異常處理
- oracle異常處理Oracle
- PowerShell 異常處理
- plsql異常處理SQL
- Swift 異常處理Swift
- JS異常處理JS
- app異常處理APP
- Oracle 處理異常Oracle
- MySQL異常處理MySql
- 異常處理 (轉)