利用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();
            }
        });

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 本篇文章介主要绍RxJava中操作符是以函数作为基本单位,与响应式编程作为结合使用的,对什么是操作、操作符都有哪些...
    嘎啦果安卓兽阅读 2,835评论 0 10
  • 一、Retrofit详解 ·Retrofit的官网地址为 : http://square.github.io/re...
    余生_d630阅读 1,807评论 0 5
  • 不同的网络请求有不同的返回结果,当同时也有很多相同的地方,比如数据的整体结构可以是这样: 如果接口数据的设计如上,...
    Little_Mango阅读 14,851评论 5 28
  • 定向:游戏,影评 标题:王者荣耀走下神坛,吃鸡是否也会想王者一样渐渐没落 (王者荣耀的系统性问题) 标题二:吃鸡并...
    忆夏_9970阅读 207评论 0 0
  • 【文】执直之智 A Pao 这是 一个我在网吧遇见的 在十年之前 拉萨 一段悠扬的笛声 功夫小子出场了 从此 我们...
    执直之智阅读 295评论 1 1