如何利用Retrofit+RxJava實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求的異常處理
通常情況下我們?cè)谂c服務(wù)器進(jìn)行通信的時(shí)候,不一定就不會(huì)出錯(cuò),有時(shí)會(huì)出現(xiàn)其他的錯(cuò)誤,這個(gè)時(shí)候我們只要和服務(wù)器約定好各種異常,在返回結(jié)果處進(jìn)行判斷,到底是執(zhí)行錯(cuò)誤,還是返回正常數(shù)據(jù)。具體的思路大致就是這樣。這里我們定義ExceptionHandle,這里我參考網(wǎng)上的東西,然后稍微做了一些改動(dòng)。
ExceptionHandle
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 ResponseException handleException(Throwable e){
//轉(zhuǎn)換成ResponseException,根據(jù)狀態(tài)碼判定錯(cuò)誤信息
ResponseException ex;
if(e instanceof HttpException){
HttpException httpException=(HttpException)e;
/**
* 傳入狀態(tài)碼,根據(jù)狀態(tài)碼判定錯(cuò)誤信息
*/
ex=new ResponseException(e,ERROR.HTTP_ERROR);
switch (httpException.code()){
case UNAUTHORIZED:
ex.message="未驗(yàn)證";
break;
case FORBIDDEN:
ex.message="服務(wù)禁止訪問(wèn)";
break;
case NOT_FOUND:
ex.message="服務(wù)不存在";
break;
case REQUEST_TIMEOUT:
ex.message="請(qǐng)求超時(shí)";
break;
case GATEWAY_TIMEOUT:
ex.message="網(wǎng)關(guān)超時(shí)";
break;
case INTERNAL_SERVER_ERROR:
ex.message="服務(wù)器內(nèi)部錯(cuò)誤";
break;
case BAD_GATEWAY:
break;
case SERVICE_UNAVAILABLE:
break;
default:
ex.message = "網(wǎng)絡(luò)錯(cuò)誤";
break;
}
return ex;
}else if(e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException){
ex=new ResponseException(e,ERROR.PARSE_ERROR);
ex.message="解析錯(cuò)誤";
return ex;
}else if(e instanceof ConnectException){
ex=new ResponseException(e,ERROR.NETWORD_ERROR);
ex.message="連接失敗";
return ex;
}else if(e instanceof javax.net.ssl.SSLHandshakeException){
ex=new ResponseException(e,ERROR.SSL_ERROR);
ex.message="證書(shū)驗(yàn)證失敗";
return ex;
}else {
ex=new ResponseException(e,ERROR.UNKNOWN);
ex.message="未知錯(cuò)誤";
return ex;
}
}
/**
* 約定異常
*/
public static class ERROR{
/**
* 自定義異常
*/
private static final int UNAUTHORIZED = 401;//請(qǐng)求用戶進(jìn)行身份驗(yàn)證
private static final int UNREQUEST=403;//服務(wù)器理解請(qǐng)求客戶端的請(qǐng)求,但是拒絕執(zhí)行此請(qǐng)求
private static final int UNFINDSOURCE=404;//服務(wù)器無(wú)法根據(jù)客戶端的請(qǐng)求找到資源
private static final int SEVERERROR=500;//服務(wù)器內(nèi)部錯(cuò)誤,無(wú)法完成請(qǐng)求。
/**
* 協(xié)議出錯(cuò)
*/
public static final int HTTP_ERROR = 1003;
/**
* 未知錯(cuò)誤
*/
public static final int UNKNOWN = 1000;
/**
* 解析錯(cuò)誤
*/
public static final int PARSE_ERROR = 1001;
/**
* 網(wǎng)絡(luò)錯(cuò)誤
*/
public static final int NETWORD_ERROR = 1002;
/**
* 證書(shū)出錯(cuò)
*/
public static final int SSL_ERROR = 1005;
}
/**
* 自定義Throwable
*/
public static class ResponseThrowable extends Exception{
public int code;
public String message;
public ResponseThrowable(Throwable throwable,int code){
super(throwable);
this.code=code;
}
}
/**
* 服務(wù)器異常
*/
public class ServerException extends RuntimeException{
public int code;
public String message;
}
/**
* 統(tǒng)一異常類,便于處理
*/
public static class ResponseException extends Exception{
public int code;
public String message;
public ResponseException (Throwable throwable,int code){
super(throwable);
this.code=code;
}
}
}
然后自己定義了一個(gè)Observer
public abstract class BaseObserver<T> implements Observer<T> {
private Context context;
public BaseObserver(Context context){
this.context=context;
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(T t) {
}
@Override
public void onError(Throwable e) {
if(e instanceof ExceptionHandle.ResponseException){
onError((ExceptionHandle.ResponseException)e);
}else{
onError(new ExceptionHandle.ResponseException(e,ExceptionHandle.ERROR.UNKNOWN));
}
}
@Override
public void onComplete() {
}
public abstract void onError(ExceptionHandle.ResponseException exception);
}
這里發(fā)生錯(cuò)誤時(shí),Observerble會(huì)先調(diào)用onError(Throwable e),按照我的寫(xiě)法呢,會(huì)繼續(xù)調(diào)用自定義onError。
那么什么時(shí)候我們對(duì)服務(wù)器的返回結(jié)果進(jìn)行判斷,什么時(shí)候該發(fā)出異常了,請(qǐng)繼續(xù)往下看:
這里我們打算用到ObservableTransformer,Transformer其實(shí)就是就是對(duì)Observable進(jìn)行一定的變換。
先看代碼:
public static class HandleFuc<T> implements Function<UserGuideSoftConfigRForm<UserGuideSoftConfigPageInfo<List<UserguideSoftConfig>>>, T> {
@Override
public T apply(UserGuideSoftConfigRForm<UserGuideSoftConfigPageInfo<List<UserguideSoftConfig>>> Response) {
if (!Response.getCode().equals("200")){
Throwable e=new Throwable("約定錯(cuò)誤");
/**
* 可以根據(jù)不同的狀態(tài)嘛返回不同的提示信息
* 與服務(wù)器約定返回異常信息
*/
ExceptionHandle.ResponseException responseException = new ExceptionHandle.ResponseException(e, ExceptionHandle.ERROR.HTTP_ERROR);
return (T) Observable.error(responseException);//發(fā)出錯(cuò)誤異常
}
return (T) Observable.just(Response);//發(fā)出服務(wù)器數(shù)據(jù),返回Observable<Response>
}
}
//處理錯(cuò)誤的變換
public static class ErrorTransformer<T> implements ObservableTransformer {
@Override
public Observable<T> apply(Observable upstream) {
return (Observable<T>) upstream.flatMap(new HandleFuc<T>());//flatMap會(huì)重新創(chuàng)建一個(gè)Observable,當(dāng)它處理完事件后會(huì)匯入原先的Observable對(duì)象。
}
}
說(shuō)明:我們的HandleFuc其實(shí)就是對(duì)服務(wù)器返回來(lái)的結(jié)果進(jìn)行判斷,邏輯很簡(jiǎn)單了,錯(cuò)誤就拋出異常直接執(zhí)行error方法。如果沒(méi)有錯(cuò)誤,就發(fā)送正常數(shù)據(jù)。這里值的說(shuō)明一點(diǎn)的是,flatMap會(huì)重新創(chuàng)建一個(gè)Observable,當(dāng)它處理完事件后會(huì)重新匯入初始的Observerble并開(kāi)始發(fā)送事件。
使用起來(lái)其實(shí)就很簡(jiǎn)單了:
@Provides
ErrorTransformer provideErrorTransformer(){
return new ErrorTransformer();
}
public Observable<UserGuideSoftConfigRForm<UserGuideSoftConfigPageInfo<List<UserguideSoftConfig>>>> getApplication(PageParmForm pageParmForm){
return retrofit.create(Service.class)
.getApplicationList(pageParmForm)
.compose(errorTransformer)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
直接用compose方法包裹起來(lái)即可。
最后看看Activity:
new NetRepository().getApplication(new PageParmForm(Constant.orderStr,Constant.pageNum,Constant.pageSize))
.subscribe(new BaseObserver<UserGuideSoftConfigRForm<UserGuideSoftConfigPageInfo<List<UserguideSoftConfig>>>>(NetWorkActivity.this) {
@Override
public void onError(ExceptionHandle.ResponseException exception) {
myToast.showToast(NetWorkActivity.this,exception.getMessage());
Log.d("carhandbook",exception.getMessage());
}
@Override
public void onNext(UserGuideSoftConfigRForm<UserGuideSoftConfigPageInfo<List<UserguideSoftConfig>>> Response) {
data=Response.getData().getList();
code=Response.getCode();
myToast.showToast(NetWorkActivity.this,code);
generateAdapter.setData(data);
generateAdapter.notifyDataSetChanged();
}
});
好了對(duì)網(wǎng)絡(luò)請(qǐng)求的異常處理整個(gè)思路大致就是這樣了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC中Json數(shù)據(jù)格式轉(zhuǎn)換
本文主要介紹了SpringMVC中Json數(shù)據(jù)格式轉(zhuǎn)換的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03
Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之貪心算法
我們可能在好多地方都會(huì)聽(tīng)到貪心算法這一概念,并且它的算法思想也比較簡(jiǎn)單就是說(shuō)算法只保證局部最優(yōu),進(jìn)而達(dá)到全局最優(yōu)。但我們實(shí)際編程的過(guò)程中用的并不是很多,究其原因可能是貪心算法使用的條件比較苛刻,所要解決的問(wèn)題必須滿足貪心選擇性質(zhì)2022-02-02
加速spring/springboot應(yīng)用啟動(dòng)速度詳解
這篇文章主要介紹了加速spring/springboot應(yīng)用啟動(dòng)速度詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì)對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
SpringBoot創(chuàng)建線程池的六種方式小結(jié)
本文主要介紹了SpringBoot創(chuàng)建線程池的六種方式小結(jié),包括自定義線程池,固定長(zhǎng)度線程池,單一線程池,共享線程池,定時(shí)線程池,SpringBoot中注入異步線程池,感興趣的可以了解一下2023-11-11
Java程序設(shè)計(jì)之12個(gè)經(jīng)典樣例
這篇文章主要給大家分享關(guān)于Java程序設(shè)計(jì)11個(gè)經(jīng)典樣例,主要以舉例的形式詳細(xì)的講解了Java程序設(shè)計(jì)的各種方法,需要的朋友可以參考一下文章具體的內(nèi)容2021-10-10
Maven中exec插件執(zhí)行Java程序的實(shí)現(xiàn)
在Maven項(xiàng)目中,可以使用Maven的插件來(lái)執(zhí)行Java程序,本文主要介紹了Maven中exec插件執(zhí)行Java程序的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12

