java - Android/RxJava 如何链接网络请求并在失败时重试

标签 java android retrofit rx-android

我正在尝试在 Android 中使用 RxJava 链接网络请求,然后在失败时重试。我一直在查看 StackOverflow,了解如何在不陷入单独使用 vanilla Android 和 Retrofit 所带来的回调 hell 的情况下执行此操作。我可以在一个过程中完成这一切,在这样的异步任务中(下面是我需要执行的步骤)登录。

  1. 使用用户名/密码登录用户
  2. 如果响应成功,则请求 SSO token
  3. 使用该 sso token 调用启动服务

我一直在 AsyncTask 中执行此操作,该操作仅在登录时有效。但是,SSO token 在应用程序使用期间过期,因此我需要在每次看到时发出请求它会过期。

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 token
  3. 之后,我需要发出第三个也是最后一个网络请求才能启动。

现在的代码只是调用登录用户,一旦成功,就会启动异步任务。理想情况下,我想在那个请求中将所有请求链接在一起。我一直在试验 flatmapmap 等,但无法弄清楚如何链接这些调用,正如我在上面提到的那样。

任何人都可以阐明这一点吗?谢谢。

最佳答案

看看这个例子。希望,它会激励你。

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

Further reading about retry

关于java - Android/RxJava 如何链接网络请求并在失败时重试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35400816/

相关文章:

java - 将 lambdaj 与 String.matches 方法结合使用

java - 在 C9.ide 上创建自定义 Java Runner(步骤 1 已完成)

java - Jython:子流程模块中出现错误,AttributeError: 'module' 对象没有属性 'python'

java - Spring MVC : Unable to get json value in jsp, 它给出 0

Android 多窗口支持 : Detecting if status bar is visible?

android - 如何在 kotlin 中使用 Retrofit 解析 xml 响应?

java - 如何将下载的文件保存在应用程序内存的缓存文件夹中?

android - 高于 maxVelocity 将方向更改为对角线,解决方法

android - 应为 BEGIN_ARRAY 但实际为 BEGIN_OBJECT

java - Retrofit 不调用 failure 并且 response.code() 是 400