如何利用Retrofit+RxJava实现网络请求的异常处理

 更新时间:2019年04月09日 15:13:54   作者:耀东wang  
这篇文章主要介绍了如何利用Retrofit+RxJava实现网络请求的异常处理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

通常情况下我们在与服务器进行通信的时候,不一定就不会出错,有时会出现其他的错误,这个时候我们只要和服务器约定好各种异常,在返回结果处进行判断,到底是执行错误,还是返回正常数据。具体的思路大致就是这样。这里我们定义ExceptionHandle,这里我参考网上的东西,然后稍微做了一些改动。

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){
    //转换成ResponseException,根据状态码判定错误信息
    ResponseException ex;
    if(e instanceof HttpException){
      HttpException httpException=(HttpException)e;
      /**
       * 传入状态码,根据状态码判定错误信息
       */
      ex=new ResponseException(e,ERROR.HTTP_ERROR);
      switch (httpException.code()){
        case UNAUTHORIZED:
          ex.message="未验证";
          break;
        case FORBIDDEN:
          ex.message="服务禁止访问";
          break;
        case NOT_FOUND:
          ex.message="服务不存在";
          break;
        case REQUEST_TIMEOUT:
          ex.message="请求超时";
          break;
        case GATEWAY_TIMEOUT:
          ex.message="网关超时";
          break;
        case INTERNAL_SERVER_ERROR:
          ex.message="服务器内部错误";
          break;
        case BAD_GATEWAY:

          break;
        case SERVICE_UNAVAILABLE:
          break;
        default:
          ex.message = "网络错误";
          break;
      }
      return ex;
    }else if(e instanceof JsonParseException
        || e instanceof JSONException
        || e instanceof ParseException){
      ex=new ResponseException(e,ERROR.PARSE_ERROR);
      ex.message="解析错误";
      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="证书验证失败";
      return ex;
    }else {
      ex=new ResponseException(e,ERROR.UNKNOWN);
      ex.message="未知错误";
      return ex;
    }
  }
  /**
   * 约定异常
   */
 public static  class ERROR{
    /**
     * 自定义异常
     */
    private static final int UNAUTHORIZED = 401;//请求用户进行身份验证
    private static final int UNREQUEST=403;//服务器理解请求客户端的请求,但是拒绝执行此请求
    private static final int UNFINDSOURCE=404;//服务器无法根据客户端的请求找到资源
    private static final int SEVERERROR=500;//服务器内部错误,无法完成请求。
    /**
     * 协议出错
     */
    public static final int HTTP_ERROR = 1003;
    /**
     * 未知错误
     */
    public static final int UNKNOWN = 1000;
    /**
     * 解析错误
     */
    public static final int PARSE_ERROR = 1001;
    /**
     * 网络错误
     */
    public static final int NETWORD_ERROR = 1002;
    /**
     * 证书出错
     */
    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;
    }
  }
  /**
   * 服务器异常
   */
  public class ServerException extends RuntimeException{
    public int code;
    public String message;
  }

  /**
   * 统一异常类,便于处理
   */
  public static class ResponseException extends Exception{
    public int code;
    public String message;
    public ResponseException (Throwable throwable,int code){
      super(throwable);
      this.code=code;
    }
  }
}

然后自己定义了一个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);
}

这里发生错误时,Observerble会先调用onError(Throwable e),按照我的写法呢,会继续调用自定义onError。

那么什么时候我们对服务器的返回结果进行判断,什么时候该发出异常了,请继续往下看:

这里我们打算用到ObservableTransformer,Transformer其实就是就是对Observable进行一定的变换。

先看代码:

  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("约定错误");
        /**
         * 可以根据不同的状态嘛返回不同的提示信息
         * 与服务器约定返回异常信息
         */
        ExceptionHandle.ResponseException responseException = new ExceptionHandle.ResponseException(e, ExceptionHandle.ERROR.HTTP_ERROR);
        return (T) Observable.error(responseException);//发出错误异常
      }
      return (T) Observable.just(Response);//发出服务器数据,返回Observable<Response>
    }
  }

  //处理错误的变换
  public static class ErrorTransformer<T> implements ObservableTransformer {
    @Override
    public Observable<T> apply(Observable upstream) {
      return (Observable<T>) upstream.flatMap(new HandleFuc<T>());//flatMap会重新创建一个Observable,当它处理完事件后会汇入原先的Observable对象。
    }
  }

说明:我们的HandleFuc其实就是对服务器返回来的结果进行判断,逻辑很简单了,错误就抛出异常直接执行error方法。如果没有错误,就发送正常数据。这里值的说明一点的是,flatMap会重新创建一个Observable,当它处理完事件后会重新汇入初始的Observerble并开始发送事件。

使用起来其实就很简单了:

@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方法包裹起来即可。

最后看看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();
      }
    });

好了对网络请求的异常处理整个思路大致就是这样了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • java集合框架线程同步代码详解

    java集合框架线程同步代码详解

    这篇文章主要介绍了java集合框架线程同步代码详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • java8新特性-Stream入门学习心得

    java8新特性-Stream入门学习心得

    这篇文章主要介绍了java8新特性-Stream入门学习心得,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 32位和64位皆适用的MyEclipse安装教程

    32位和64位皆适用的MyEclipse安装教程

    这篇文章主要为大家详细介绍了32位和64位皆适用的MyEclipse安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Java并发编程中构建自定义同步工具

    Java并发编程中构建自定义同步工具

    这篇文章主要介绍了Java并发编程中构建自定义同步工具,本文讲解了可阻塞状态依赖操作的结构、有界缓存实现基类示例、阻塞实现方式一:抛异常给调用者、阻塞实现方式二:通过轮询和休眠、阻塞实现方式三:条件队列等内容,需要的朋友可以参考下
    2015-04-04
  • 浅谈spring注解之@profile

    浅谈spring注解之@profile

    这篇文章主要介绍了浅谈spring注解之@profile,@profile通过配置来改变参数,这里整理的详细的用法,有兴趣的可以了解一下
    2017-10-10
  • Java 基于雪花算法生成分布式id

    Java 基于雪花算法生成分布式id

    SnowFlake 算法(雪花算法), 是Twitter开源的分布式id生成算法。其核心思想就是: 使用一个64 bit的long型的数字作为全局唯一id。本文讲述Java 基于雪花算法生成分布式id的方法
    2021-06-06
  • SpringMVC Mybatis配置多个数据源并切换代码详解

    SpringMVC Mybatis配置多个数据源并切换代码详解

    这篇文章主要介绍了SpringMVC Mybatis配置多个数据源并切换代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Java线程中synchronized和volatile关键字的区别详解

    Java线程中synchronized和volatile关键字的区别详解

    这篇文章主要介绍了Java线程中synchronized和volatile关键字的区别详解,synchronzied既能够保障可见性,又能保证原子性,而volatile只能保证可见性,无法保证原子性,volatile不需要加锁,比synchronized更轻量级,不会阻塞线程,需要的朋友可以参考下
    2024-01-01
  • 使用Spring注入Hibernate验证框架

    使用Spring注入Hibernate验证框架

    这篇文章主要介绍了使用Spring注入Hibernate验证框架方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • java语言如何生成plist下载ipa文件

    java语言如何生成plist下载ipa文件

    这篇文章主要介绍了java语言如何生成plist下载ipa文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08

最新评论