Retry a call with Retrofit 2 and RxJava2 after displaying a dialog

前端 未结 2 884
被撕碎了的回忆
被撕碎了的回忆 2021-02-04 17:32

I\'m calling an API using Retrofit 2 and RxJava2. If a call fails, in some cases (e.g. no Internet connection), I want to display an error dialog to the user and let him retry.<

相关标签:
2条回答
  • 2021-02-04 17:55
    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*/)
    }));
    

    When button is clicked you trigger this event:

    retrySubject.onNext(new Object());
    

    As you can see in this Marble diagram:

    the error is not propagated. The retryWhen operator will indeed handle it and do a proper action. This is the reason why you have to enable (or for example show a Dialog) in doOnError, before retryWhen operator.

    When you don't want to listen anymore for successive retry attempts, you just need to unsubscribe:

    disposable.dispose();
    

    As per your question:

    What should I do if I want to retry only on a specific Exception but not on the other ones?

    You can modify your retryWhen in this way:

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

    Where Throwables.propagate(throwable) is a Guava util that can be replaced with throw new RuntimeException(throwable);

    0 讨论(0)
  • 2021-02-04 17:58

    for me i am using clean architecture and it was hard to put android code to show dialog in usecase or repository. so since i was using kotlin i passed in a lamba to take care of things for me. something like this:

    here is my full presenter:

     class WeatherDetailsPresenter @Inject constructor(var getCurrentWeatherWithForecastUsecase: GetCurrentWithForcastedWeatherUsecase) : BaseMvpPresenter<WeatherDetailsView>() {
    
        fun presentCurrentAndForcastedWeather(country: String?) {
            getCurrentWeatherWithForecastUsecase.takeUnless { country?.isBlank() == true }?.apply {
                this.countyName = country
                execute(object : DefaultSubscriber<Pair<CurrentWeatherModel, ForecastedWeatherModel>>() {
                    override fun onSubscribe(d: Disposable) {
                        super.onSubscribe(d)
                        showLoading(true)
                    }
    
                    override fun onNext(t: Pair<CurrentWeatherModel, ForecastedWeatherModel>) {
                        super.onNext(t)
                        view?.showCurrentWeather(t.first)
                        view?.showForcastWeather(t.second)
                    }
    
                    override fun onError(e: Throwable) {
                        super.onError(e)
    //if i get an error pass in lambda to the dialog
                        myErrorDialog.setretryAction( {this@WeatherDetailsPresenter.presentCurrentAndForcastedWeather(country)})
                    }
    
                    override fun onComplete() {
                        super.onComplete()
                        showLoading(false)
                    }
                })
            } ?: run { view?.showCountryUnavailable() }
        }
    

    then in then errordialog i do this assuming its a dialogfragment:

    lateinit var retryAction: () -> Unit
    
    override fun onStart() {
            super.onStart()
            dialog.window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
            button.setOnClickListener { dismiss();retryAction() }
        }
    

    my code for on error is not acutally like that but just to give you an idea on how to pass in a lambda. im sure you can pass in a function of your own. in this case the lambda was the method itself to retry.

    0 讨论(0)
提交回复
热议问题