Android/RxJava Как связать сетевые запросы и повторить попытку в случае сбоя

Я пытаюсь связать сетевые запросы с помощью RxJava в Android, а затем повторить попытку при сбое. Я просматривал Stackru о том, как сделать это, не попадая в ад Callback, который приходит с использованием одного только Android и Retrofit. Я могу сделать все это в процедуре, в асинхронной задаче, подобной этой (ниже приведены шаги, которые мне нужно сделать), чтобы войти в систему.

  1. Войти в систему с именем пользователя / паролем
  2. Запросить токен SSO, если этот ответ успешен
  3. Вызовите сервис запуска с этим токеном sso

Я делал это в AsyncTask это работало только при входе в систему. Однако токен единого входа истекает во время использования приложения, поэтому мне нужно делать запрос каждый раз, когда я вижу, что срок его действия истекает.

Код для AsyncTask выглядит следующим образом:

private class LoginUserTask extends AsyncTask<Void, Void, Void> {
    private final String LOG_TAG = LoginUserTask.class.getSimpleName();

    @Override
    protected Void doInBackground(Void... params) {
        OkHttpClient httpClient = ((TribeSocial) getApplication()).getHttpClient();

        // Login User
        GroupDockService groupDockLoginService =
                GroupDockServiceGenerator
                        .createService(GroupDockService.class,
                                httpClient, GroupDockUser.class, new GroupDockUserDeserializer());
        GroupDockUser groupDockUser = groupDockLoginService.loginUser("Tribe", username, password);
        Utility.saveAccountSubdomain(mContext, groupDockUser.getGroupDockSubdomain().getSubdomain());

        // Get Sso Token
        GroupDockService groupDockService = GroupDockServiceGenerator
                .createService(GroupDockService.class, httpClient);
        GroupDockSsoResponse ssoResponse =
                groupDockService.getSsoToken(Utility.getAccountSubdomain(mContext), true);
        Utility.saveSsoToken(mContext, ssoResponse.getSsoToken());

        // Sign in user into Tribe service
        TribeSocialService tribeSocialLaunchService =
                TribeServiceGenerator.createService(TribeSocialService.class,
                        httpClient, new LenientGsonConverter(new Gson()));
        tribeSocialLaunchService.launch(Utility.getSsoToken(mContext));

        // Get User id and save it to SharedPreferences
        TribeSocialService tribeSocialWhoAmIService =
                TribeServiceGenerator.createService(TribeSocialService.class, httpClient,
                        User.class, new WhoAmIDeserializer());
        User tribeUser = tribeSocialWhoAmIService.whoami();
        Utility.saveUserId(mContext, tribeUser.getId());

        return null;
    }

    @Override
    protected void onPostExecute(Void v) {
        Utility.launchMainActivity(mContext);
    }
}

Моя попытка сделать эту работу с RxJava что-то вроде

GroupDockService groupDockLoginService =
        GroupDockServiceGenerator
                .createService(GroupDockService.class,
                        mHttpClient, GroupDockUser.class, new GroupDockUserDeserializer());

groupDockLoginService
        .loginUserRx("Tribe", username, password)
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<GroupDockUser>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {
                Log.e(LOG_TAG, "I have errored out: " + e.getMessage());
                Toast.makeText(mContext,
                        getString(R.string.username_and_or_password_is_incorrect),
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNext(GroupDockUser groupDockUser) {
                Utility.saveUsernamePassword(mContext, username, password);
                new LoginUserTask().execute();
            }
        });

В этом коде мне нужно сделать следующее

  1. Когда loginUserRx завершается успешно, мне нужно сохранить имя пользователя и пароль в SavedPreferences
  2. Затем мне нужно сделать сетевой запрос, чтобы получить токен SSO
  3. После этого мне нужно сделать третий и последний сетевой запрос на запуск.

Код прямо сейчас делает вызов для входа в систему пользователя, и, как только это успешно, запускает асинхронную задачу. В идеале я хотел бы объединить запросы в один запрос. Я экспериментировал с flatmap, mapи т. д., и не могу понять, как связать эти вызовы, как я уже говорил выше.

Кто-нибудь может пролить свет на это? Благодарю.

1 ответ

Решение

Посмотрите на этот пример. Надеюсь, это вас вдохновит.

service
        //do login
        .loginUser()
        //side effect: save into Shared Preference
        .doOnNext( )
        //get SSO
        .flatMap()
        //do any other side effects
        .doOnNext()
        //do final network request
        .flatMap()
        //in case of error retry after 5 seconds
        .retryWhen(observable -> Observable.timer(5, TimeUnit.SECONDS))
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        //update you UI
        .subscribe();

Дальнейшее чтение о повторной попытке

Другие вопросы по тегам