如何使用 RXJava 和 Retrofit 重试连接服务器?

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

代码

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();

}

国家模型

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;
    }

}

正如您在 onError 方法中看到的那样,我希望当用户单击重试按钮时必须再次重试与服务器的调用。

我花了 3 天时间阅读有关 retryWhen 方法的文章,并试图理解这张图片,但我无法理解它,而且我不知道如何在我的场景中使用它。

我的问题就是这样 我把赏金留给了可以帮助我的人,你可以在这里留下你的答案并在那里分享你的答案,直到我可以给你赏金。

我的解决方案很简单,只是 temporary/hack 而不是花几天时间使用 retryWhen()。 - 下面的代码我将您的请求调用封装到一个函数中。 -如果出现网络错误,只需对该函数进行递归调用,直到成功。

    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();
}

}); }

我找不到任何解决方案,所以我决定使用 retryUntil 而不是 retryWhen,因为我没有找到任何答案。