2017-12-06 11 views
2

Retrofit 2とRxJava2を使用してAPIを呼び出しています。 呼び出しが失敗した場合(インターネットに接続していないなど)、ユーザーにエラーダイアログを表示して再試行させたい場合があります。ダイアログを表示した後、Retrofit 2とRxJava2を使用してコールを再試行してください。

私は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"); 
        }); 
} 
+0

に置き換えることができます.com/a/47631107/1584654 – GVillani82

+0

@ GVillani82例を試しましたが、いくつか質問があります。#1パブリッシャーが決して放出しないとどうなりますか?保留中の再試行は永遠に保留されますか? #2特定の例外に対してのみ再試行したいが、他の例外では再試行しない場合はどうすればよいですか? #3 'retryWhen'が定義されている場合、エラーエラーは発生しません。 – Eselfar

+0

前の例で実際にいくつかの間違いがありました。とにかく答えを書き直して、あなたの質問に答えようとしました。 – GVillani82

答えて

1
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*/) 
})); 

retrySubject.onNext(new Object()); 

あなたは、この大理石の図に見ることができるように:ここでは

は、現時点で私が持っているコードです

enter image description here

エラーは伝播されません。 retryWhenオペレータは実際にそれを処理し、適切な処置を行います。このため、にretryWhenオペレータの前に有効にする(またはたとえばダイアログを表示する)必要があります。

あなたは連続した再試行のためにもう聞きたくない場合は、あなただけ解除する必要があります:あなたの質問を1として

disposable.dispose(); 

私がしたい場合、私は何をすべき特定のExceptionでのみ再試行しますが、他のものにはない を再試行しますか?

あなたはこの方法であなたのretryWhenを変更することができます。https:// stackoverflowのThrowables.propagate(throwable)はそのutilのグアバある

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

が、私は最近、同様の質問に答えthrow new RuntimeException(throwable);

+0

ありがとう!私はそれが今どのように機能しているかをよりよく理解していると思う。 :) – Eselfar

+0

私も! :Dそれを説明しようとしたので私は以前の解決策で私が間違っていたことを実感しました。ありがとう! – GVillani82

関連する問題