Retrofit RxJava优雅的处理服务器返回异常错误分解.docx

上传人:b****8 文档编号:29732168 上传时间:2023-07-26 格式:DOCX 页数:19 大小:34.83KB
下载 相关 举报
Retrofit RxJava优雅的处理服务器返回异常错误分解.docx_第1页
第1页 / 共19页
Retrofit RxJava优雅的处理服务器返回异常错误分解.docx_第2页
第2页 / 共19页
Retrofit RxJava优雅的处理服务器返回异常错误分解.docx_第3页
第3页 / 共19页
Retrofit RxJava优雅的处理服务器返回异常错误分解.docx_第4页
第4页 / 共19页
Retrofit RxJava优雅的处理服务器返回异常错误分解.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

Retrofit RxJava优雅的处理服务器返回异常错误分解.docx

《Retrofit RxJava优雅的处理服务器返回异常错误分解.docx》由会员分享,可在线阅读,更多相关《Retrofit RxJava优雅的处理服务器返回异常错误分解.docx(19页珍藏版)》请在冰豆网上搜索。

Retrofit RxJava优雅的处理服务器返回异常错误分解.docx

RetrofitRxJava优雅的处理服务器返回异常错误分解

Retrofit+RxJava优雅的处理服务器返回异常、错误

异常&错误

实际开发经常有这种情况,比如登录请求,接口返回的

信息包括请求返回的状态:

失败还是成功,错误码,User对象等等。

如果网络等原因引起的登录失败可以归结为异常,如果是用户信息输入错误导致的登录失败算是错误。

假如服务器返回的是统一数据格式:

/**

*标准数据格式

*@param

*/

publicclassResponse{

publicintstate;

publicStringmessage;

publicTdata;

}

网络异常导致的登录失败,在使用Retrofit+RxJava请求时都会直接调用subscribe的onError事件;

密码错误导致的登录失败,在使用Retrofit+RxJava请求时都会调用subscribe的onNext事件;

无论是异常还是错误,都要在subscribe里面处理异常信息,如下代码:

APIWrapper.getInstance().login("username","password")

.subscribe(newObserver>(){

@Override

publicvoidonCompleted(){

}

@Override

publicvoidonError(Throwablee){

}

@Override

publicvoidonNext(Responsedata){

if(data.state==1001){

//.....

}elseif(data.state==1002){

}

}

});

现在我希望在发生任何错误的情况下,都会调用onError事件,并且由model来处理错误信息。

那么,此时我们就应该有一个ExceptionEngine来处理事件流中的错误信息了。

在工作流中处理异常

在正常情况下,我们获取网络数据的流程通常如下:

请求接口->解析数据->更新UI

整个数据请求过程都是发生在Rx中的工作流之中。

当有异常产生的时候,我们要尽量不在ui层里面进行判断,换句话说,我们没有必要去告诉ui层具体的错误信息,只需要让他弹出一个信息(Toast或者Dialog)展示我们给它的信息就行。

请求接口和数据解析都可能出错,所以在这两层进行错误处理。

为了更好的解耦,我们通过拦截器拦截错误,然后根据错误类型分发信息。

拦截器

数据解析层的拦截器

这个拦截器主要是为了获取具体的错误信息,分发给上层的UI,给用户以提示,增强用户体验。

publicObservablegetWeather(StringcityName){

returnweatherService.getWeather(cityName)

//拦截服务器返回的错误

.map(newServerResponseFunc())

//HttpResultFunc()为拦截onError事件的拦截器,后面会讲到,这里先忽略

.onErrorResumeNext(newHttpResponseFunc());

}

//拦截固定格式的公共数据类型Response,判断里面的状态码

privateclassServerResponseFuncimplementsFunc1,T>{

@Override

publicTcall(Responsereponse){

//对返回码进行判断,如果不是0,则证明服务器端返回错误信息了,便根据跟服务器约定好的错误码去解析异常

if(reponse.state!

=0){

//如果服务器端有错误信息返回,那么抛出异常,让下面的方法去捕获异常做统一处理

thrownewServerException(reponse.state,reponse.message);

}

//服务器请求数据成功,返回里面的数据实体

returnreponse.data;

}

}

所以整个逻辑是这样的:

所以在前三步的过程中,只要发生异常(服务器返回的错误也抛出了)都会抛出,这时候就触发了RxJava的OnError事件。

处理onError事件的拦截器

这个拦截器主要是将异常信息转化为用户”能看懂”的友好提示。

privateclassHttpResponseFuncimplementsFunc1>{

@Override

publicObservablecall(Throwablethrowable){

//ExceptionEngine为处理异常的驱动器

returnObservable.error(ExceptionEngine.handleException(throwable));

}

}

两个拦截器以前使用,代码如下:

publicObservablegetWeather(StringcityName){

returnweatherService.getWeather(cityName)

//拦截服务器返回的错误

.map(newServerResponseFunc())

//HttpResponseFunc()为拦截onError事件的拦截器

.onErrorResumeNext(newHttpResponseFunc());

}

调用:

APIWrapper.getInstance().getWeather("北京")

.subscribe(newSampleProgressObserver(MainActivity.this){

@Override

publicvoidonNext(WeatherBeanweatherBean){

tv.setText(weatherBean.toString());

}

});

相关类:

publicclassRxSubscriberextendsErrorSubscriber{

@Override

publicvoidonStart(){

super.onStart();

DialogHelper.showProgressDlg(context,"正在加载数据");

}

@Override

publicvoidonCompleted(){

DialogHelper.stopProgressDlg();

}

@Override

protectedvoidonError(ApiExceptionex){

DialogHelper.stopProgressDlg();

Toast.makeText(context,ex.message,Toast.LENGTH_SHORT).show();

}

@Override

publicvoidonNext(Tt){

}

}

publicabstractclassErrorSubscriberextendsObserver{

@Override

publicvoidonError(Throwablee){

if(einstanceofApiException){

onError((ApiException)e);

}else{

onError(newApiException(e,123));

}

}

/**

*错误回调

*/

protectedabstractvoidonError(ApiExceptionex);

}

处理异常的驱动器

package;

import.ParseException;

importcom.google.gson.JsonParseException;

importorg.json.JSONException;

import.ConnectException;

importretrofit2.adapter.rxjava.HttpException;

/**

*CreatedbyLzxon2016/7/11.

*/

publicclassExceptionEngine{

//对应HTTP的状态码

privatestaticfinalintUNAUTHORIZED=401;

privatestaticfinalintFORBIDDEN=403;

privatestaticfinalintNOT_FOUND=404;

privatestaticfinalintREQUEST_TIMEOUT=408;

privatestaticfinalintINTERNAL_SERVER_ERROR=500;

privatestaticfinalintBAD_GATEWAY=502;

privatestaticfinalintSERVICE_UNAVAILABLE=503;

privatestaticfinalintGATEWAY_TIMEOUT=504;

publicstaticApiExceptionhandleException(Throwablee){

ApiExceptionex;

if(einstanceofHttpException){//HTTP错误

HttpExceptionhttpException=(HttpException)e;

ex=newApiException(e,ERROR.HTTP_ERROR);

switch(httpException.code()){

caseUNAUTHORIZED:

caseFORBIDDEN:

caseNOT_FOUND:

caseREQUEST_TIMEOUT:

caseGATEWAY_TIMEOUT:

caseINTERNAL_SERVER_ERROR:

caseBAD_GATEWAY:

caseSERVICE_UNAVAILABLE:

default:

ex.message="网络错误";//均视为网络错误

break;

}

returnex;

}elseif(einstanceofServerException){//服务器返回的错误

ServerExceptionresultException=(ServerException)e;

ex=newApiException(resultException,resultException.code);

ex.message=resultException.message;

returnex;

}elseif(einstanceofJsonParseException

||einstanceofJSONException

||einstanceofParseException){

ex=newApiException(e,ERROR.PARSE_ERROR);

ex.message="解析错误";//均视为解析错误

returnex;

}elseif(einstanceofConnectException){

ex=newApiException(e,ERROR.NETWORD_ERROR);

ex.message="连接失败";//均视为网络错误

returnex;

}else{

ex=newApiException(e,ERROR.UNKNOWN);

ex.message="未知错误";//未知错误

returnex;

}

}

}

/**

*约定异常

*/

publicclassERROR{

/**

*未知错误

*/

publicstaticfinalintUNKNOWN=1000;

/**

*解析错误

*/

publicstaticfinalintPARSE_ERROR=1001;

/**

*网络错误

*/

publicstaticfinalintNETWORD_ERROR=1002;

/**

*协议出错

*/

publicstaticfinalintHTTP_ERROR=1003;

}

publicclassApiExceptionextendsException{

publicintcode;

publicStringmessage;

publicApiException(Throwablethrowable,intcode){

super(throwable);

this.code=code;

}

}

publicclassServerExceptionextendsRuntimeException{

publicintcode;

publicStringmessage;

}

DialogHelper.Java

publicclassDialogHelper{

/**

*通用Dialog

*

*/

//因为本类不是activity所以通过继承接口的方法获取到点击的事件

publicinterfaceOnOkClickListener{

abstractvoidonOkClick();

}

/**

*Listener

*/

publicinterfaceOnCancelClickListener{

abstractvoidonCancelClick();

}

privatestaticAlertDialogmDialog;

publicstaticvoidshowDialog(Contextcontext,Stringtitle,Stringcontent,finalOnOkClickListenerlistenerYes,

finalOnCancelClickListenerlistenerNo){

showDialog(context,context.getString(android.R.string.ok),context.getString(android.R.string.cancel),title,content,listenerYes,listenerNo);

}

publicstaticvoidshowDialog(Contextcontext,Stringok,Stringcancel,Stringtitle,Stringcontent,finalOnOkClickListenerlistenerYes,

finalOnCancelClickListenerlistenerNo){

AlertDialog.Builderbuilder=newAlertDialog.Builder(context);

builder.setMessage(content);

//设置title

builder.setTitle(title);

//设置确定按钮,固定用法声明一个按钮用这个setPositiveButton

builder.setPositiveButton(ok,

newDialogInterface.OnClickListener(){

publicvoidonClick(DialogInterfacedialog,intwhich){

//如果确定被电击

if(listenerYes!

=null){

listenerYes.onOkClick();

}

mDialog=null;

}

});

//设置取消按钮,固定用法声明第二个按钮要用setNegativeButton

builder.setNegativeButton(cancel,

newDialogInterface.OnClickListener(){

publicvoidonClick(DialogInterfacedialog,intwhich){

//如果取消被点击

if(listenerNo!

=null){

listenerNo.onCancelClick();

}

mDialog=null;

}

});

//控制这个dialog可不可以按返回键,true为可以,false为不可以

builder.setCancelable(false);

//显示dialog

mDialog=builder.create();

if(!

mDialog.isShowing())

mDialog.show();

}

publicstaticvoidshowDialog(Contextcontext,intok,intcancel,inttitle,intcontent,finalOnOkClickListenerlistenerYes,

finalOnCancelClickListenerlistenerNo){

showDialog(context,context.getString(ok),context.getString(cancel),context.getString(title),context.getString(content),listenerYes,listenerNo);

}

staticProgressDialogprogressDlg=null;

/**

*启动进度条

*

*@paramstrMessage进度条显示的信息

*@param//当前的activity

*/

publicstaticvoidshowProgressDlg(Contextctx,StringstrMessage){

if(null==progressDlg){

if(ctx==null)return;

progressDlg=newProgressDialog(ctx);

//设置进度条样式

progressDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);

//提示的消息

progressDlg.setMessage(strMessage);

progressDlg.setIndeterminate(false);

progressDlg.setCancelable(true);

progressDlg.show();

}

}

publicstaticvoidshowProgressDlg(Contextctx){

showProgressDlg(ctx,"");

}

/**

*结束进度条

*/

publicstaticvoidstopProgressDlg(){

if(null!

=progressDlg&&progressDlg.isShowing()){

progressDlg.dismiss();

progressDlg=null;

}

if(null!

=dialog&&dialog.isShowing()){

dialog.dismiss();

dialog=null;

}

}

privatestaticDialogdialog;

publicstaticvoidshowDialogForLoading(Contextcontext,Stringmsg,booleancancelable){

if(null==dialog){

if(null==context)return;

Viewview=LayoutInflater.from(context).inflate(R.layout.layout_loading_dialog,null);

TextViewloadingText=(TextView)view.findViewById(R.id.loading_tip_text);

loadingText.setText(msg);

dialog=newDialog(context,R.style.loading_dialog_style);

dialog.setCancelable(cancelable);

dialog.setCanceledOnTouchOutside(cancelable);

dialog.setContentView(iew,newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));

Activityactivity=(Activity)context;

if(activity.isFinishing())return;

dialog.show();

}

}

}

可能本博客也不是最好的解决方案,如果有更好的想法,我愿与你互相交流!

分享:

Retrofit+RxJava错误预处理

看到bobo_wang的文章,不仅感觉有受益匪浅,这里做下介绍。

首先定义如下Transformer转换器。

publicstaticObservable.Transformer,T>sTransformer(){

returnresponseObservable->responseObservable.map(tResponse->{

if(!

tResponse.success)thrownewRuntimeExcept

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 实习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1