IO

时间:2017-10-16 14:27:42

标签: android rx-java rx-android

问题

由于缺少授权令牌,当其中一个API调用因失败而尝试注销我的用户时。但我无法将Schedulers.io()上的操作与SharedPrefs.commit()同步。所有呼叫都是同时进行的,因此所有呼叫都会尝试同时注销。 我想要实现的是只有第一个触发注销,剩下两个注意到,它发生并且根本没有触发任何东西。

建筑

我有3个API调用,使用令牌自动激活。 令牌保存在SharedPrefs内。 所有API调用都在Schedulers.io()上进行。 当调用令牌刷新失败时,我尝试使用注销方法从SharedPrefs删除数据。

以下是注销方法代码:

 Flowable.fromCallable { isUserLogged() }
            .filter { it }
            .flatMap { logoutUseCase.execute() }
            .doOnComplete { showLogin() }
            .subscribeOn(Schedulers.single())
            .blockingSubscribe()

此方法在与Authenticator相关联的OkHttpClient类中调用Retrofit

2 个答案:

答案 0 :(得分:0)

您可以使用Observable.amb()运算符来解决竞争问题。

如果每个API调用在没有身份验证令牌时发出错误,那么您可以将它们组织起来:

Observable.amb( apiCall1Observable, apiCall2Observable, apiCall3Observable )
  .observeOn(Schedulers.io())
  .doOnError( error -> {
    logoutUseCase.execute()
   } )
  .subscribe( value -> {
   },
   error -> {
   });

amb()运算符将选择第一个发布值或终止事件。这将触发只会执行一次的logoutUseCase.execute()

关键是重构各个API调用的状态,将有关注销的时间和位置的决定推向更高的级别。

答案 1 :(得分:0)

我设法以非常简单的方式解决了我的问题。 由于Authenticator仅在 -

时触发
  来自远程Web服务器或代理服务器的

身份验证质询

发生,因此我可以同步负责刷新令牌的代码部分。这样,每当发生刷新令牌失败时,logout()方法将被同步,并且每个调用中的数据都会更新。

<强> CODE

override fun authenticate(route: Route, response: Response): Request? {
    synchronized(this, {
      ###refresh token code###
    })
}