How can I retry to connect with the server using RXJava and Retrofit?

Viewed 170

Code

new Retrofit.Builder().baseUrl(Constants.BASE_URL_FILES).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build().create(RetrofitInterface.class).getCountries().observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<List<CountryModel>>() {
    @Override
    public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
        MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull List<CountryModel> countryModels) {
        fragmentCountriesBinding.fragmentCountriesRecyclerViewCountries.setAdapter(new CountriesAdapter(requireContext(), countryModels));
        MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
    }

    @Override
    public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
        MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
        if (!MainActivity.isNetworkConnected(requireContext()))
            Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.no_internet, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).setAction(R.string.retry, view ->
            {

            }).show();
        else
            Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.something_went_wrong, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).show();
    }
});

RetrofitInterface

public interface RetrofitInterface {

    @GET("GetCountries.php")
    Single<List<CountryModel>> getCountries();

}

CountryModel

public class CountryModel {

    private int countryId;
    private String countryName, countryIcon;

    public int getCountryId() {
        return countryId;
    }

    public String getCountryName() {
        return countryName;
    }

    public String getCountryIcon() {
        return countryIcon;
    }

}

As you can see inside the onError method, I want when the user clicks on the retry button must retry the call with the server again.

I read the articles talking about retryWhen method and tried to understand this image, but I can't understand it. And I don't know how to use it with my scenario.

The Image

My problem is like this question exactly.

2 Answers

My solution is simple and just a temporary/hack rather than spending couple of days using retryWhen().

  • In the code below, I encapsulate your request call to a function.

  • If there is a network error, just do a recursive call with the function until it will be successful.

      private void sendRequest(){
          new Retrofit.Builder().baseUrl(Constants.BASE_URL_FILES).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build().create(RetrofitInterface.class).getCountries().observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<List<CountryModel>>() {
              @Override
              public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
                  MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.VISIBLE);
              }
    
              @Override
              public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull List<CountryModel> countryModels) {
                  fragmentCountriesBinding.fragmentCountriesRecyclerViewCountries.setAdapter(new CountriesAdapter(requireContext(), countryModels));
                  MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
              }
    
              @Override
              public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
                  MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
                  if (!MainActivity.isNetworkConnected(requireContext()))
                      Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.no_internet, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).setAction(R.string.retry, view ->
                      {
    
                      }).show();
                   // IF NO NETWORK AVAILABLE just do recursive call of the method
                 sendRequest();
                  else
                      Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.something_went_wrong, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).show();
              }
          });
      }
    

I didn’t reach a solution, so I decided to use retryUntil instead of retryWhen.

Related