【问题标题】:Repeat a Retrofit2.0 api-call based on the server response根据服务器响应重复 Retrofit2.0 api-call
【发布时间】:2018-03-10 03:18:47
【问题描述】:

使用 Retrofit2(版本:2.3.0)、OkHTTP3(版本:3.9.0)和 RxJava2(版本:2.0.0)

rest api 调用场景

 Observable<ServerResponse> backendService.isUserVerified("someuserName") 

返回 200 Ok HTTP

如果用户被验证,预期的成功响应 JSON POJO

{

  user: "someUserName",

  isVerified: "yes"

}

如果用户未通过验证,则预期的成功响应 JSON POJO

{

  user: "someUserName",

  isVerified: "no"

}

以下是我正在尝试实现的代码

 backendService.isUserVerified("someuserName")
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())

  //Want to add a flatmap (or some other operator)
  .flatmap(new Function<ServerResponse>, ObservableSource<?>>(){
            @Override
            public ObservableSource<?> apply(ServerResponse serverResponse) throws Exception {
                if(0 != serverResponse.getisVerified.compareToIgnoreCase("yes")) {
                return Observable.error(new CustomException());
             }
             return //current observable.
  }

 .retryWhen(mRetryHandler)
 .subscribeWith(observer);

目的是在验证 == no 时抛出自定义异常,以便 retryWhen() 操作员可以参与重复调用链,否则希望通过链继续直到 subscribe()。

任何指针/帮助?

【问题讨论】:

  • 你能解释更多你想要做什么吗?你想用你想继续的替换ObservableResource&lt;?&gt;
  • Yes ObservableSource 用于错误和失败场景...

标签: retrofit rx-java retrofit2 rx-android rx-java2


【解决方案1】:

您可以只使用doOnNext 而不是flatmap

backendService.isUserVerified("someuserName")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

//we can throw an exception if the user is not verified or keep the response as it is otherwise
.doOnNext(serverResponse -> {
                        if(0 != serverResponse.getisVerified.compareToIgnoreCase("yes")) 
                        {
                            throw new CustomException();
                        }
                    })

.retryWhen(mRetryHandler)
.subscribeWith(observer);

doOnNext 操作符只是对发射的项目执行一个函数而不改变它。您只想根据项目在特定情况下抛出错误,否则不要更改它,因此它是一个合适的运算符。由于您不会在 doOnNext 运算符之前或之后更改线程,因此在使用下一个运算符中的项目之前,您知道它将在继续之前抛出异常,以防它应该抛出它。

这是运营商链接文档中的一个示例:

Observable.just(1, 2, 3)
      .doOnNext(new Action1<Integer>() {
      @Override
      public void call(Integer item) {
        if( item > 1 ) {
          throw new RuntimeException( "Item exceeds maximum value" );
        }
      }
    }).subscribe(new Subscriber<Integer>() {
    @Override
    public void onNext(Integer item) {
        System.out.println("Next: " + item);
    }
    @Override
    public void onError(Throwable error) {
        System.err.println("Error: " + error.getMessage());
    }
    @Override
    public void onCompleted() {
        System.out.println("Sequence complete.");
    }
});

[输出:]

下一个:1

错误:项目超过最大值

【讨论】:

    【解决方案2】:

    如果你想使用Observable.error(new CustomException()); 抛出一个错误,你不需要为错误返回一个特定的对象和另一个返回预期答案的函数,这是一个异常,将转到onError() 方法.您的ObservableResource&lt;?&gt; 必须返回您在onResponse() 方法中从Subscriber 检索到的预期答案。如果您使用Observable.error() 抛出错误,您的链将被破坏,错误将转到onError()

    编辑

    你应该使用retry函数,因为它会返回ServerResponse,你可以检查它是否有效。使用retryWhen,您只会在出现问题时收到错误消息。在你的情况下,你没有得到任何错误,你得到了答案。在这种情况下,您不需要 flatMap

    .retry(new BiPredicate<ServerResponse, Throwable>() {
               @Override
               public boolean test(ServerResponse serverResponse, Throwable throwable) throws Exception {
                   return serverResponse.getisVerified.equals("no");
               }
         })
    

    【讨论】:

    • 我猜你错过了链中下面的重试运算符......它将消耗抛出的异常。我的问题正是关于如何创建这个 observable。
    • 实际上我需要对 "getisVerified.equals("no")" 和错误场景进行 api 重试。
    • 如果你从我的回答中仔细观察retry 函数,你会得到它们。
    猜你喜欢
    • 1970-01-01
    • 2017-04-13
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 2013-01-08
    • 1970-01-01
    相关资源
    最近更新 更多