显示对话框后,使用Retrofit 2和RxJava2重试呼叫

Ese*_*far 6 android rx-java2 retrywhen

我正在使用Retrofit 2和RxJava2调用API。如果呼叫失败,在某些情况下(例如,没有Internet连接),我想向用户显示错误对话框,然后让他重试。

当我使用RxJava时,我正在考虑使用它,.retryWhen(...)但是我不知道该怎么做,因为它需要等待用户按下对话框上的按钮。

目前,我显示该对话框,但在用户按下任何按钮之前会重试。另外,我希望在用户按下“取消”时不重试该呼叫。

这是我目前的代码:

private void displayDialog(DialogInterface.OnClickListener positive, DialogInterface.OnClickListener negative) {
    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    builder.setMessage("Unexpected error, do you want to retry?")
            .setPositiveButton("Retry", positive)
            .setNegativeButton("Cancel", negative)
            .show();
}

private Observable<Boolean> notifyUser() {
    final PublishSubject<Boolean> subject = PublishSubject.create();
    displayDialog(
            (dialogInterface, i) -> subject.onNext(true),
            (dialogInterface, i) -> subject.onNext(false)
    );

    return subject;
}

private void onClick() {
    Log.d(TAG, "onClick");
    getData()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .retryWhen(attempts -> {
                return attempts.zipWith(
                        notifyUser(),
                        (throwable, res) -> res);
            })
            .subscribe(
                    s -> {
                        Log.d(TAG, "success");
                    });
}
Run Code Online (Sandbox Code Playgroud)

GVi*_*i82 8

final PublishSubject<Object> retrySubject = PublishSubject.create();

disposable.add(getData()
    .doOnError(throwable -> enableButton())
    .retryWhen(observable -> observable.zipWith(retrySubject, (o, o2) -> o))
    .subscribeWith(/* do what you want with the result*/)
}));
Run Code Online (Sandbox Code Playgroud)

单击按钮时,将触发此事件:

retrySubject.onNext(new Object());
Run Code Online (Sandbox Code Playgroud)

正如您在此大理石图中所看到的:

在此处输入图片说明

错误不会传播。该retryWhen运营商的确会处理,并做适当的处理。这就是为什么必须doOnErrorretryWhen操作符之前启用(或显示对话框)的原因。

当您不想再听后续重试尝试时,只需取消订阅即可:

disposable.dispose();
Run Code Online (Sandbox Code Playgroud)

根据您的问题:

如果我只想重试特定的异常而不重试其他异常,该怎么办?

您可以通过retryWhen以下方式进行修改:

.retryWhen(throwableObservable -> throwableObservable.flatMap(throwable -> {
      if (throwable instanceof TargetException) {
          return Observable.just(throwable).zipWith(retrySubject, (o, o2) -> o);
      } else {
          throw Throwables.propagate(throwable);
      }
}))
Run Code Online (Sandbox Code Playgroud)

Throwables.propagate(throwable)可以用替换的Guava util 在哪里throw new RuntimeException(throwable);

  • 我正在使用Kotlin`.retryWhen(observable-&gt; observable.zipWith(retrySubject,(o,o2)-&gt; o))`导致编译错误(可能是我不理解lambda语法的错误),但是我可以使用它这个简单的代码:`.retryWhen {retrySubject.toFlowable(BackpressureStrategy.LATEST)}` (2认同)