问题
由于缺少授权令牌,当其中一个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
答案 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###
})
}