【问题标题】:rx java retrofit 2 error handlingrx java 改造 2 错误处理
【发布时间】:2016-03-30 12:29:20
【问题描述】:

我正在使用改造 2 和 rx java

情况: 该应用程序发送一些请求,然后我得到自动转换为用户 dto 的 json 格式的响应,然后在 rx java 的 onNext 方法中我收到用户列表。如果我从服务器收到这样的消息怎么办:{"error":"can't get the list of users"}

如何使用改造 2 和 rx 处理这种情况?

      Subscription subscriptionBranches = model.getRepoBranches(owner, name)
                    .map(branchesMapper)
                    .subscribe(new Observer<List<Branch>>() {
                        @Override
                        public void onCompleted() {
                            ;
                        }

                        @Override
                        public void onError(Throwable e) {
                            if (e instanceof retrofit.HttpException) {
                                HttpException exception = (HttpException) e;
                            }
                            showError(e);
                        }

                        @Override
                        public void onNext(List<Branch> list) {
                            branchList = list;
                            view.showBranches(list);
                        }
                    });

            addSubscription(subscriptionBranches);
.....
    @Override
    public Observable<List<RepositoryDTO>> getRepoList(String name) {
        return apiInterface
                .getRepositories(name)
                .compose(applySchedulers());
    }

【问题讨论】:

标签: android retrofit rx-java


【解决方案1】:

根据服务器响应,您可能会或可能不会进入onError 函数。如果服务器返回非 2XX http 状态代码,您将进入 onError 方法。另一方面,如果您获得 2XX http 状态代码,您将输入 onNext

我假设您可以处理onNext 位,我将在onError 中解释您如何做到这一点。重要的是要意识到有很多方法可以做到这一点,这只是一个使用 okhttp 3retrofit 2 beta4 的示例。

因此,retrofit2 表示,在使用 rxjava 时,每个非 2XX 的 http 响应都是 HttpExceptions。这个你已经在你的代码中有它了:

if (e instanceof retrofit.HttpException) {
   HttpException exception = (HttpException) e;
}

现在您要做的是获取响应的正文。这可以通过在HttpException 中调用Response response = exception.response() 来实现。通过响应,获取错误正文非常简单。您只需致电response.errorBody()。然后,您可以将主体转换为 java 对象或仅将其作为字符串访问。

由于您有一个 json 错误正文作为示例,因此您可以将响应正文转换为 java 对象:

new GsonConverterFactory().responseBodyConverter(type,
      new Annotation[0]).convert(response.errorBody());

其中type 是表示错误的java 对象的类。

因此,将它们放在一起,在您的 onError 方法中,您可以编写如下内容:

if (e instanceof retrofit.HttpException) {
   HttpException exception = (HttpException) e;
   Response response = exception.response();
   Converter<ResponseBody, MyError> converter = new GsonConverterFactory()
       .responseBodyConverter(MyError.class, Annotation[0]);
   MyError error = converter.convert(response.errorBody());
}

MyError 是一个模型,代表您在问题中遇到的错误 json。

【讨论】:

  • 谢谢伙计,很酷的方式。我使用 Result> 实现它有点不同,然后我只是使用 gson 将 responseBodyResponse.response().errorBody().byteStream() 转换为对象。你的方法其实比我的好。
  • @Fred 好答案!你可以检查这个类似的问题,但在我的情况下处理 2xx http 代码:stackoverflow.com/questions/43047055/…
  • 注解?这是什么?
  • @SaifulAzad 恐怕我没有得到你的评论。你能更具体吗?您指的是哪个注释?
  • 啊。谢谢你的回复,虽然你很害怕。顺便说一句,我已经解决了。再次感谢您的回答。
【解决方案2】:

我相信在您提到的情况下,您只会进入您的onError 处理,因为改造将无法反序列化您的响应,因为它没有格式化为List。您可以根据异常类型来处理您的案例。

如果您无法更改 api 以返回一致的响应类型,则必须考虑使用 TypedInput,可能还有转换器。

此外,虽然它可能与手头的情况并不完全相关/矫枉过正,但TypeAdapters 值得一提。他们将让您确定 retrofit 如何在每个类的基础上反序列化 gson

Gson gson = new GsonBuilder()
    .registerTypeAdapter(MyClass.class, new MyAdapter())
    .create();

RestAdapter adapter = new RestAdapter.Builder()
    .setConverter(new GsonConverter(gson))
    .build();

【讨论】:

    【解决方案3】:

    我遇到了同样的情况,发生错误时我可以从服务器获取 json 的方式是这样的:

    retrofit2.Response<TokenRefresh> r = call.execute();
    
    String errorMessage = "";
    try {
        errorMessage = r.errorBody().string();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Timber.d("errorMessage: " + errorMessage);
    

    【讨论】:

      猜你喜欢
      • 2016-12-20
      • 2016-03-03
      • 2016-03-05
      • 2017-06-30
      • 2016-05-03
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      相关资源
      最近更新 更多