Retrofit+RxJava优雅的处理服务器返回异常、错误_第1页
Retrofit+RxJava优雅的处理服务器返回异常、错误_第2页
Retrofit+RxJava优雅的处理服务器返回异常、错误_第3页
Retrofit+RxJava优雅的处理服务器返回异常、错误_第4页
Retrofit+RxJava优雅的处理服务器返回异常、错误_第5页
免费预览已结束,剩余9页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Retrofit+RxJava 优雅的处理服务器返异常、错误异常 &错误实际开发经常有这种情况,比如登录请求,接口返回的 信息包括请求返回的状态:失败还是成功,错误码, User 对象等等。如果网络等原因引起 的登录失败可以归结为异常,如果是用户信息输入错误导致的登录失败算是错误。假如服务器返回的是统一数据格式:/* 标准数据格式* param <T>*/public class Response<T> public int state;public String message; public T data;网络异常导致的登录失败, 在使用 Retrofit+

2、RxJava 请求时都会直接调用 subscribe 的 onError 事件;密码错误导致的登录失败, 在使用 Retrofit+RxJava 请求时都会调用 subscribe 的 onNext 事件; 无论是异常还是错误,都要在 subscribe 里面处理异常信息,如下代码:APIWrapper.getInstance().login("username", "password").subscribe(new Observer<Response<User>>() Override public void onComplet

3、ed() Overridepublic void onError(Throwable e) Overridepublic void onNext(Response<User> data) if(data.state = 1001)/else if(data.state = 1002) );现在我希望在发生任何错误的情况下,都会调用 onError 事件,并且由 model 来处理错误信 息。那么,此时我们就应该有一个 ExceptionEngine 来处理事件流中的错误信息了。在工作流中处理异常 在正常情况下,我们获取网络数据的流程通常如下: 请求接口 ->解析数据->

4、 更新UI 整个数据请求过程都是发生在 Rx 中的工作流之中。当有异常产生的时候,我们要尽量不在 ui 层里面进行判断,换句话说,我们没有必要去告诉 ui 层具体的错误信息,只需要让他弹 出一个信息( Toast 或者 Dialog )展示我们给它的信息就行。请求接口和数据解析都可能出错, 所以在这两层进行错误处理。 为了更好的解耦, 我们通过 拦截器拦截错误,然后根据错误类型分发信息。拦截器 数据解析层的拦截器UI ,给用户以提示,增强用户这个拦截器主要是为了获取具体的错误信息,分发给上层的 体验。public Observable<Weather> getWeather(Str

5、ing cityName)return weatherService.getWeather(cityName) /拦截服务器返回的错误 .map(new ServerResponseFunc<Weather>() /HttpResultFunc ()为拦截 onError 事件的拦截器,后面会讲到,这里先忽略.onErrorResumeNext(new HttpResponseFunc<Weather>();/拦截固定格式的公共数据类型Response<T>判断里面的状态码private class ServerResponseFunc<T> i

6、mplements Func1<Response<T>, T> Overridepublic T call(Response<T> reponse) /对返回码进行判断,如果不是0,则证明服务器端返回错误信息了,便根据跟服务器约定好的错误码去解析异常if (reponse.state != 0) /如果服务器端有错误信息返回,那么抛出异常,让下面的方法去捕获异常做统一处理throw new ServerExce pti on(repon se.state,re pon se.message);/服务器请求数据成功,返回里面的数据实体retur n repon

7、 se.data;所以整个逻辑是这样的:您S胃FraV” El A更申勺-所以在前三步的过程中,只要发生异常(服务器返回的错误也抛出了)都会抛出,这时候就触发了 RxJava 的 OnError 事件。頁冒耳累PM V Cl朴豊14处理onError事件的拦截器 这个拦截器主要是将异常信息转化为用户”能看懂”的友好提示。p rivate class Http Res pon seF un c<T> impi eme nts Fun c1<Throwable, Observable<T>> Overridep ublic Observable<T>

8、 call(Throwable throwable) /ExceptionEngine为处理异常的驱动器return Observable.error(Exce ptio nEn gi ne.ha ndleExce ptio n(throwable);两个拦截器以前使用,代码如下:P ublic Observable<Weather> getWeather(Stri ng cityName)return weatherService.getWeather(cityName)拦截服务器返回的错误.ma p(new ServerRes pon seF un c<Weather&g

9、t;()/Htt pRes pon seFu nc ()为拦截on Error事件的拦截器.on ErrorResumeNext( new Htt pRes pon seF un c<Weather>();调用:APIWrapper.getlnstance().getWeather(” 北京”).subscnbe( newSampleProgressObserver<Weather>(MainActivity.this) Override public void onNext(WeatherBean weatherBean) tv.setText(weatherBean

10、.toString(););相关类:public class RxSubscriber<T> extends ErrorSubscriber<T> Override public void onStart() super.onStart(); DialogHelper.showProgressDlg(context, " 正在加载数据 ");Overridepublic void onCompleted() DialogHelper.stopProgressDlg(); Overrideprotected void onError(ApiExcept

11、ion ex) DialogHelper.stopProgressDlg();Toast.makeText(context, ex.message, Toast.LENGTH_SHORT).show(); Override public void onNext(T t) public abstract class ErrorSubscriber<T> extends Observer<T> Overridepublic void onError(Throwable e) if(e instanceof ApiException) onError(ApiException

12、)e);else onError(new ApiException(e,123);/* 错误回调*/protected abstract void onError(ApiException ex);处理异常的驱动器package ;import .ParseException;import com.google.gson.JsonParseException;import org.json.JSONException;import .ConnectException;import retrofit2.adapter.rxjava.HttpException;/* Created by Lzx

13、on 2016/7/11. */public class ExceptionEngine /对应 HTTP 的状态码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 f

14、inal int BAD_GA TEWAY = 502;private static final int SERVICE_UNA VAILABLE = 503; private static final int GATEW AY_TIMEOUT = 504;public static ApiException handleException(Throwable e)ApiException ex;if (e instanceof HttpException) /HTTP 错误 HttpException httpException = (HttpException) e; ex = new A

15、piException(e, ERROR.HTTP_ERROR); switch(httpException.code()case UNAUTHORIZED:case FORBIDDEN:case NOT_FOUND:case REQUEST_TIMEOUT:case GATEWAY_TIMEOUT:case INTERNAL_SERVER_ERROR: case BAD_GA TEWAY:case SERVICE_UNA VAILABLE: default:ex.message = "网络错误 " /均视为网络错误 break; return ex; else if (e

16、 instanceof ServerException)/ 服务器返回的错误ServerException resultException = (ServerException) e; ex = new ApiException(resultException, resultException.code); ex.message = resultException.message; return ex; else if (e instanceof JsonParseException| e instanceof JSONException| e instanceof ParseExceptio

17、n)ex = new ApiException(e, ERROR.PARSE_ERROR); ex.message = "解析错误 "/均视为解析错误return ex;else if(e instanceof ConnectException)ex = new ApiException(e, ERROR.NETWORD_ERROR); ex.message = "连接失败 " /均视为网络错误 return ex;else ex = new ApiException(e, ERROR.UNKNOWN); ex.message = "未知错误

18、"/ 未知错误return ex;/* 约定异常*/public class ERROR /* 未知错误*/public static final int UNKNOWN = 1000; /* 解析错误*/public static final int PARSE_ERROR = 1001; /* 网络错误*/public static final int NETWORD_ERROR = 1002; /* 协议出错*/public static final int HTTP_ERROR = 1003; public class ApiException extends Excepti

19、on public int code;public String message;public ApiException(Throwable throwable, int code) super(throwable); this.code = code;public class ServerException extends RuntimeException public int code;public String message;DialogHelper.Javapublic class DialogHelper /* 通用 Dialog*/ 因为本类不是 activity 所以通过继承接

20、口的方法获取到点击的事件 public interface OnOkClickListener abstract void onOkClick();/* Listener*/public interface OnCancelClickListener abstract void onCancelClick();private static AlertDialog mDialog;public static void showDialog(Context context, String title, String content, final OnOkClickListener listener

21、Yes,final OnCancelClickListener listenerNo) showDialog(context, context.getString(android.R.string.ok), context.getString(android.R.string.cancel), title, content, listenerYes, listenerNo);public static void showDialog(Context context, String ok, String cancel, String title, String content, final On

22、OkClickListener listenerYes,final OnCancelClickListener listenerNo) AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(content);/ 设置 title builder.setTitle(title);setPositiveButton/ 设置确定按钮,固定用法声明一个按钮用这个 builder.setPositiveButton(ok, new DialogInterface.OnClickListener

23、() public void onClick(DialogInterface dialog, int which) / 如果确定被电击 if (listenerYes != null) listenerYes.onOkClick(); mDialog = null;);固定用法声明第二个按钮要用setNegativeButton/ 设置取消按钮, builder.setNegativeButton(cancel, new DialogInterface.OnClickListener() public void onClick(DialogInterface dialog, int which

24、) / 如果取消被点击 if (listenerNo != null) listenerNo.onCancelClick(); mDialog = null;);/ 控制这个 dialog 可不可以按返回键, true 为可以, false 为不可以 builder.setCancelable(false);/ 显示 dialogmDialog = builder.create();if (!mDialog.isShowing()mDialog.show();public static void showDialog(Context context, int ok, int cancel, i

25、nt title, int content, final OnOkClickListener listenerYes,final OnCancelClickListener listenerNo) showDialog(context, context.getString(ok), context.getString(cancel), context.getString(title), context.getString(content), listenerYes, listenerNo);static ProgressDialog progressDlg = null;/* 启动进度条* p

26、aram strMessage 进度条显示的信息* param /当前的 activity*/public static void showProgressDlg(Context ctx, String strMessage) if (null = progressDlg) if (ctx = null) return;progressDlg = new ProgressDialog(ctx);/设置进度条样式 progressDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);/提示的消息 progressDlg.setMessage(str

27、Message); progressDlg.setIndeterminate(false); progressDlg.setCancelable(true); progressDlg.show();public static void showProgressDlg(Context ctx) showProgressDlg(ctx, "");/* 结束进度条*/public static void stopProgressDlg() if (null != progressDlg && progressDlg.isShowing() progressDlg.

28、dismiss(); progressDlg = null;if (null != dialog && dialog.isShowing() dialog.dismiss(); dialog = null;private static Dialog dialog;public static void showDialogForLoading(Context context, String msg, boolean cancelable) if (null = dialog) if (null = context) return;View view = LayoutInflate

29、r.from(context).inflate(R.layout.layout_loading_dialog,null);TextView loadingText = (TextView)view.findViewById(R.id.loading_tip_text); loadingText.setText(msg);newdialog = new Dialog(context, R.style.loading_dialog_style); dialog.setCancelable(cancelable); dialog.setCanceledOnTouchOutside(cancelabl

30、e); dialog.setContentView(iew,LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);Activity activity = (Activity) context;if (activity.isFinishing() return;dialog.show();可能本博客也不是最好的解决方案,如果有更好的想法,我愿与你互相交流! 分享: Retrofit+RxJava 错误预处理 看到 bobo_wang 的文章,

31、不仅感觉有受益匪浅,这里做下介绍。首先定义如下 Transformer 转换器。public static <T> Observable.Transformer<Response<T>, T> sTransformer() return responseObservable -> responseObservable.map(tResponse -> if (!tResponse.success) throw new RuntimeException(tResponse.code); return tRata;).onErrorResumeNex

32、t(new HttpResponseFunc<>();public static <T> Observable.Transformer<T, T> switchSchedulers() return observable -> observable.subscribeOn(Schedulers.io() .observeOn(AndroidSchedulers.mainThread();private static class HttpResponseFunc<T> implements Func1<Throwable, Observ

33、able<T>> Override public Observable<T> call(Throwable throwable) /ExceptionEngine 为处理异常的驱动器return Observable.error(new Throwable(throwable);调用:public void login(View v)apiservice.login(name,pwd).compose(Transformers.sTransformer().compose(Transformers.switchSchedulers().subscribe(subs

34、criber);private Subscriber<UserModel> subscriber = new Subscriber<UserModel>() Override public void onCompleted() / do onCompletedOverride public void onError(Throwable e) / do on success != true;/ do on http error/ do on other errorOverride public void onNext(UserModel model) / parse da

35、ta;接口:FormUrlEncoded POST("interface?login")Observable<Response<UserModel>> login(Field("name") String name,Field("pwd") String pwd);最后再来点干货。Transformer 和 Func处理的区别如上的处理,定义了 从中可以明显感觉的到一个 sTransformer 和一个 HttpResponseFunc,sTransformer 其实也是可以用 Func1 来定义的 ,publ

36、ic void login(View v)apiservice.login(name,pwd).compose(Transformers.switchSchedulers() .map(new TransFuc<UserModel>() .onErrorReturn(new HttpResponseFunc<>() .subscribe(subscriber);public static class TransFuc<T> implements Func1<Response<T>, T> Override public T call(Response<T> tResponse) if (!tResponse.success) throw new RuntimeException(tResponse.code); r

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论