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

时间:2016-02-15 02:57:42

标签: java android retrofit rx-android

我正在尝试在Android中使用RxJava链接网络请求,然后在失败时重试。我一直在关注StackOverflow如何做到这一点,而没有进入单独使用vanilla Android和Retrofit的Callback地狱。我可以在一个过程中完成所有这一切,在这样的异步任务中(下面是我需要做的步骤)登录。

  1. 使用用户名/密码登录用户
  2. 如果响应成功,则请求SSO令牌
  3. 使用该sso令牌调用启动服务
  4. 我一直在AsyncTask执行此操作,只有在登录时才有效。但是,SSO令牌在应用程序使用时到期,所以每次看到该请求时我都需要发出请求它过期了。

    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. 之后,我需要发布第三个也是最后一个网络请求。
    4. 现在代码只是调用登录用户,一旦成功,就启动异步任务。理想情况下,我想在一个请求中将所有请求链接在一起。我一直在尝试使用flatmapmap等等,并且无法解决如何在我走出上面时将这些调用链接起来。

      任何人都可以对此有所了解吗?感谢。

1 个答案:

答案 0 :(得分:8)

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

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