目前,我有一个变量来指示标记刷新是否在Authenticator
中进行,在这种情况下,我取消Interceptor
中的所有后续请求,用户必须手动刷新页面,否则我可以注销用户并强制用户登录。
对于上述问题,使用OKHTTP3.x for Android有什么好的解决方案或架构?
编辑:我想解决的问题是一般的,我不想顺序我的电话。也就是说,等待一个调用完成并刷新令牌,然后只在活动和片段级别上发送请求的其余部分。
public class CustomAuthenticator implements Authenticator {
@Inject AccountManager accountManager;
@Inject @AccountType String accountType;
@Inject @AuthTokenType String authTokenType;
@Inject
public ApiAuthenticator(@ForApplication Context context) {
}
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Invaidate authToken
String accessToken = accountManager.peekAuthToken(account, authTokenType);
if (accessToken != null) {
accountManager.invalidateAuthToken(accountType, accessToken);
}
try {
// Get new refresh token. This invokes custom AccountAuthenticator which makes a call to get new refresh token.
accessToken = accountManager.blockingGetAuthToken(account, authTokenType, false);
if (accessToken != null) {
Request.Builder requestBuilder = response.request().newBuilder();
// Add headers with new refreshToken
return requestBuilder.build();
} catch (Throwable t) {
Timber.e(t, t.getLocalizedMessage());
}
}
return null;
}
}
需要注意的是,AccountManager.BlockingGetAuthToken
(或非阻塞版本)仍然可以在其他地方调用,而不是拦截器。因此,防止此问题发生的正确位置是在身份验证器中。
我们希望确保需要访问令牌的第一个线程将检索它,可能的其他线程应该注册回调,以便在第一个线程完成检索令牌时调用。
好消息是,AbstractAccountAuthEnticator
已经有一种传递异步结果的方法,即AccountAuthEnticatorResponse
,您可以在该方法上调用onResult
或onError
。
下面的示例由3个块组成。
第一个是关于确保只有一个线程获取访问令牌,而其他线程只是注册它们的响应
以进行回调。
第二部分只是一个虚拟的空结果包。在这里,您将加载您的令牌,可能刷新它,等等。
第三部分是一旦你有了你的结果(或错误)你会做什么。您必须确保为可能注册的每个其他线程调用响应。
boolean fetchingToken;
List<AccountAuthenticatorResponse> queue = null;
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
synchronized (this) {
if (fetchingToken) {
// another thread is already working on it, register for callback
List<AccountAuthenticatorResponse> q = queue;
if (q == null) {
q = new ArrayList<>();
queue = q;
}
q.add(response);
// we return null, the result will be sent with the `response`
return null;
}
// we have to fetch the token, and return the result other threads
fetchingToken = true;
}
// load access token, refresh with refresh token, whatever
// ... todo ...
Bundle result = Bundle.EMPTY;
// loop to make sure we don't drop any responses
for ( ; ; ) {
List<AccountAuthenticatorResponse> q;
synchronized (this) {
// get list with responses waiting for result
q = queue;
if (q == null) {
fetchingToken = false;
// we're done, nobody is waiting for a response, return
return null;
}
queue = null;
}
// inform other threads about the result
for (AccountAuthenticatorResponse r : q) {
r.onResult(result); // return result
}
// repeat for the case another thread registered for callback
// while we were busy calling others
}
}
只要确保在使用响应
时在所有路径上返回null
即可。
显然,您可以使用其他方法来同步这些代码块,比如@Matrix在另一个响应中所示的atomics。我使用了synchronized
,因为我认为这是最容易掌握的实现,因为这是一个很好的问题,每个人都应该这样做;)
上面的示例是这里描述的发射器循环的一个改编版本,其中详细介绍了并发性。如果您对RxJava的工作原理感兴趣,这个博客是一个很好的来源。
我试图从比特币市场RESTful API中获取不同的JSON。 问题是:我只能将单个GET请求逐个发送到API,因此我无法同时从所有比特币市场获取所有数据。 有没有办法使用Python线程(每个线程使用不同的客户端端口发送GET请求)同时获取多个数据?
XMLHttpRequest 对象用于和服务器交换数据。 向服务器发送请求 如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:xmlhttp.open("GET","ajax_info.txt",true); xmlhttp.send(); 方法 描述 open(method,url,async) 规定请求的类型、URL 以及是否异步处理
下面是官方指南中的GCM Android集成示例。 特别是,我对上述链接类中的以下行感到困惑: 现在,每当我的主要活动启动时,我都会调用intent服务,我相信instanceID负责启动令牌刷新。 我是否应该在每次从我的主要活动启动此GCM注册意图时检查Shared Prefs值。但是,在这种情况下刷新将失败,因为在初始令牌获取之后,条件将始终为true。 我应该放弃共享prefs逻辑吗?这样每
我的一个EC2实例上有一个graphql服务器正在运行。我也有AWS appsync运行,但目前它只与几个Lambda集成。 我想将我的Appsync连接到graphql服务器,这样Appsync将作为特定查询/变化的代理。 因此,从客户端来看,它将如下所示: 客户端将一个查询发送到APPESNC,让我们假设它看起来像这样: Appsync已经定义了一个查询,它被配置为在graphql服务器上代理
在行引发异常: 线程“main”javax.net.ssl.SSLHandShaker异常:Sun.Security.Validator.ValidatoreXception:PKIX路径构建失败:Sun.Security.Provider.CertPath.SunCertPathBuilderException:无法在Sun.Security.SSL.Alerts.GetSleXception(
我想我调用AWS存储网关refreshCache方法的频率太高了(如消息所示),但我不确定我需要等待多长时间,直到我再次点击它,任何帮助都将是感激的。 com.amazonaws.services.StorageGateway.model.InvalidGatewayRequestException:向服务器发送的请求太多。(服务:AwsStorageGateway;状态代码:400;错误代码:I