首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >改进2.0 + RxJava + Error JSON body

改进2.0 + RxJava + Error JSON body
EN

Stack Overflow用户
提问于 2015-11-29 07:32:14
回答 2查看 5.5K关注 0票数 18

我对RxJava和Retrofit非常陌生,正在尝试用它来编写我的应用程序接口调用。所有API调用在出错时都返回JSON主体,其一般格式为,

代码语言:javascript
复制
{"errors":[{"code":100, "message":"Login/Password not valid", "arguments":null}]}

目前我的登录API调用的代码(其他也是类似的)是,

代码语言:javascript
复制
mConnect.login(id, password)
        .subscribe(new Subscriber<Token>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted()");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError(): " + e);
                if (e instanceof HttpException) {
                  // dump e.response().errorBody()
                }
            }

            @Override
            public void onNext(Token token) {
                Log.d(TAG, "onNext(): " + token);
            }
        });

当我在onError()中遇到错误时,我希望自动将错误主体中的JSON解码为POJO并使用它。有没有办法做到这一点,最好是在一个地方的所有其他API调用。任何帮助都是非常感谢的。

EN

回答 2

Stack Overflow用户

发布于 2016-03-25 01:37:25

我建议使用可重用的TransformeronErrorResumeNext运算符来封装您的逻辑。它看起来像这样:

代码语言:javascript
复制
<T> Observable.Transformer<T, T> parseHttpErrors() {
    return new Observable.Transformer<T, T>() {
        @Override
        public Observable<T> call(Observable<T> observable) {
            return observable.onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() {
                @Override
                public Observable<? extends T> call(Throwable throwable) {
                    if (throwable instanceof HttpException) {
                        HttpErrorPojo errorPojo = // deserialize throwable.response().errorBody();

                        // Here you have two options, one is report this pojo back as error (onError() will be called),
                        return Observable.error(errorPojo); // in this case HttpErrorPojo would need to inherit from Throwable

                        // or report this pojo back as part of onNext()
                        return Observable.just(errorPojo); //in this case HttpErrorPojo would need to inherit from <T>
                    }
                    // if not the kind we're interested in, then just report the same error to onError()
                    return Observable.error(throwable);
                }
            });
        }
    };
}

注意代码中的注释,因为您必须决定是报告解析后的响应onError()还是onNext()。

然后,您可以在API调用中的任何位置使用此转换器,如下所示:

代码语言:javascript
复制
mConnect.login(id, password)
        .compose(this.<Token>parseHttpErrors()) // <-- HERE
        .subscribe(new Subscriber<Token>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted()");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError(): " + e);
                if (e instanceof HttpErrorPojo) {
                  // this will be called if errorPojo was reported via Observable.error()
                }
            }

            @Override
            public void onNext(Token token) {
                Log.d(TAG, "onNext(): " + token);
                if (token instanceof HttpErrorPojo) {
                  // this will be called if errorPojo was reported via Observable.just()
                }
            }
        });
票数 6
EN

Stack Overflow用户

发布于 2016-05-11 21:35:02

反序列化可能也是一个问题。您可以使用retrofit converter to deserialize it (也可以自己动手)。

我的解决方案在murki的基础上增加了一点:

代码语言:javascript
复制
<T> Observable.Transformer<T, T> parseHttpErrors() {
        return new Observable.Transformer<T, T>() {
            @Override
            public Observable<T> call(Observable<T> observable) {
                return observable.onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() {
                    @Override
                    public Observable<? extends T> call(Throwable throwable) {
                        if ( throwable instanceof HttpException ) {
                            Retrofit retrofit = new Retrofit.Builder()
                                    .baseUrl(SERVER_URL) // write your url here
                                    .addConverterFactory(GsonConverterFactory.create())
                                    .build();
                            Converter<ResponseBody, Error> errorConverter =
                                    retrofit.responseBodyConverter(Error.class, new Annotation[0]);
                            // Convert the error body into our Error type.
                            try {
                                Error error = errorConverter.convert(((HttpException) throwable).response().errorBody());
                                // Here you have two options, one is report this pojo back as error (onError() will be called),
                                return Observable.error(new Throwable(error.getMessage()));
                            }
                            catch (Exception e2) {
                                return Observable.error(new Throwable());
                            }

                        }
                        // if not the kind we're interested in, then just report the same error to onError()
                        return Observable.error(throwable);
                    }
                });
            }
        };
    }

然后在onError()中,

代码语言:javascript
复制
@Override
public void onError(Throwable e) {
    progressBar.setVisibility(View.GONE); // optional 
    if ( !TextUtils.isEmpty(e.getMessage()) ) {
            // show error as you like 
            return;
    }
    // show a default error if you wish
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33977686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档