Retrofit2+Rxjava作為主流的網(wǎng)絡(luò)請求框架,本文主要講解針對網(wǎng)絡(luò)請求的錯(cuò)誤信息進(jìn)行一次封裝,方便我們根據(jù)返回的狀態(tài)合理地在UI界面進(jìn)行顯示,同時(shí)如何主動(dòng)取消網(wǎng)絡(luò)請求的訂閱。
網(wǎng)絡(luò)請求中有很多常見的錯(cuò)誤,我們可以通過Toast彈出消息通知用戶具體的異常以及加載對應(yīng)的UI界面。除此之外,通過具體的異常信息,方便我們及時(shí)的排查項(xiàng)目中的BUG。那么我們就需要知道具體的錯(cuò)誤是什么。Retrofit2回調(diào)方法有四種,分別是:onSubscribe(),onNext()、onError()和onComplete(),他們的意思分別是:訂閱、下一步、失敗和完成。通常我們在onNext()和onError()方法中處理成功和失敗的操作。onNext()中獲取到數(shù)據(jù)的返回進(jìn)行展示,那么在onError()中只給我們一個(gè)Throwable,那么我們該如何處理呢?
一下是一個(gè)簡單的網(wǎng)絡(luò)請求,先看代碼:
userNetWork.toGetLunBoTuEntity(new Observer<LunBoTuEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(LunBoTuEntity lunBoTuEntity) {
if (lunBoTuEntity.isSuccess()) {
Toast.makeText(MainActivity.this, "網(wǎng)絡(luò)請求成功", Toast.LENGTH_SHORT).show();
} else {
}
}
@Override
public void onError(Throwable e) {
//對網(wǎng)絡(luò)請求錯(cuò)誤統(tǒng)一封裝處理
String errorMessage = ErrorHandler.errorMessage(e);
Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
}
});
在這里可以注意到以下一行代碼,這個(gè)就是本文的重點(diǎn),對網(wǎng)絡(luò)請求返回的錯(cuò)誤做統(tǒng)一處理:
//對網(wǎng)絡(luò)請求錯(cuò)誤統(tǒng)一封裝處理
String errorMessage = ErrorHandler.errorMessage(e);
要對返回錯(cuò)誤作統(tǒng)一處理,那么就要封裝返回?cái)?shù)據(jù)及異常類型判斷,這就要從服務(wù)器返回的數(shù)據(jù)格式說起了。我們一般請求的返回都是像下面這樣
{
"Success": false
"code":"200",
"message":"Successd!",
"data":{
"name":"小明"
"age":3
"date":"2017-05-12"
}
}
服務(wù)器端返回?cái)?shù)據(jù)約定俗稱就是大概以上的格式??赡芫唧w的code碼表示的含義不一樣,這個(gè)可以與服務(wù)器端人員交流,靈活變化,對于上述的服務(wù)器返回?cái)?shù)據(jù)我們要對errorCode做出一些判斷,可以根據(jù)自己的業(yè)務(wù)需要做出不同的操作:
public static String errorMessage(Throwable e) {
TradeSimpleResult errBody = ErrorHandler.handle(e);
if (errBody != null) {
final Activity activity = AppManager.topActivity();
String errorCode = errBody.getErrorInfo().getErrorCode();
if (activity != null && !activity.isDestroyed()) {
if ("401".equals(errorCode)) {
//token失效了
} else if ("402".equals(errorCode)) {
} else if ("403".equals(errorCode)) {
} else if ("404".equals(errorCode)) {
}else if ("500".equals(errorCode)){
}
}
return errBody.getErrorInfo().getErrorMessage();
}
return "";
}
對服務(wù)器返回?cái)?shù)據(jù)我們要對code做出一些判斷,code不為200(假設(shè)200表示請求網(wǎng)絡(luò)成功)就拋出異常。所以我們新建一個(gè)TradeSimpleResult類,對應(yīng)上面的數(shù)據(jù)結(jié)構(gòu)。
下面這個(gè)實(shí)體類這算是所有實(shí)體的一個(gè)基類,data可以為任何數(shù)據(jù)類型。然后要對返回結(jié)果進(jìn)行預(yù)處理,新建一個(gè)ExceptionHandle。預(yù)處理無非就是根據(jù)返回?cái)?shù)據(jù)用Gson進(jìn)行解析,Success若為true則正常處理,否則拋出異常讓ExceptionHandle進(jìn)一步處理,判斷異常為何種異常。
以下為TradeSimpleResult實(shí)體類的基類:
public class TradeSimpleResult implements Serializable{
private boolean Success;
private int StatusCode;
private String Message;
private ErrorInfoBean ErrorInfo;
public boolean isSuccess() {
return Success;
}
public void setSuccess(boolean Success) {
this.Success = Success;
}
public int getStatusCode() {
return StatusCode;
}
public void setStatusCode(int StatusCode) {
this.StatusCode = StatusCode;
}
public String getMessage() {
return Message;
}
public void setMessage(String Message) {
this.Message = Message;
}
public ErrorInfoBean getErrorInfo() {
return ErrorInfo;
}
public void setErrorInfo(ErrorInfoBean ErrorInfo) {
this.ErrorInfo = ErrorInfo;
}
public static class ErrorInfoBean {
private String ErrorMessage;
private String ErrorCode;
public String getErrorMessage() {
return ErrorMessage;
}
public void setErrorMessage(String ErrorMessage) {
this.ErrorMessage = ErrorMessage;
}
public String getErrorCode() {
return ErrorCode;
}
public void setErrorCode(String ErrorCode) {
this.ErrorCode = ErrorCode;
}
}
}
那么實(shí)體類的基類我們也封裝好了,就來看看具體封裝的ErrorHandler的代碼操作:
public class ErrorHandler {
private static String data = "{\"Success\": false,\"StatusCode\": 500,\"Message\": \"處理失敗\", \"ErrorInfo\": {\"ErrorMessage\": \"網(wǎng)絡(luò)請求錯(cuò)誤\",\"ErrorCode\": \"404\" },\"Result\": null}";
public static TradeSimpleResult handle(Throwable throwable) {
if (throwable instanceof HttpException) {
HttpException error = (HttpException) throwable;
try {
String string = error.response().errorBody().string();
if (isJSONValid(string)) {
return new Gson().fromJson(string, TradeSimpleResult.class);
} else {
return new Gson().fromJson(data, TradeSimpleResult.class);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
throwable.printStackTrace();
return null;
}
}
public static String errorMessage(Throwable e) {
TradeSimpleResult errBody = ErrorHandler.handle(e);
if (errBody != null) {
final Activity activity = AppManager.topActivity();
String errorCode = errBody.getErrorInfo().getErrorCode();
if (activity != null && !activity.isDestroyed()) {
if ("401".equals(errorCode)) {
//token失效了
} else if ("402".equals(errorCode)) {
} else if ("403".equals(errorCode)) {
} else if ("404".equals(errorCode)) {
}else if ("500".equals(errorCode)){
}
}
return errBody.getErrorInfo().getErrorMessage();
}
return "";
}
public final static boolean isJSONValid(String jsonInString) {
try {
return true;
} catch (Exception e) {
return false;
}
}
}
需要注意的是以上操作需要用到Gson對數(shù)據(jù)進(jìn)行json格式的解析,那么到現(xiàn)在為止,網(wǎng)絡(luò)請求的錯(cuò)誤返回的封裝處理就做完了,使用的話,直接在onError(Throwable e)的方法中String errorMessage = ErrorHandler.errorMessage(e);就可以拿到具體的錯(cuò)誤信息了。
源碼下載地址:https://download.csdn.net/download/weitao_666/11116700