最近,我不得不与一个使用Retrofit 1,okhttp3,jobManager和Picasso 2.71828的大型旧项目合作。应用程序从服务器接收数据。交互逻辑:用户登录,接收令牌,刷新令牌。它们存储在与 shHelper 的共享首选项中。使用令牌,他可以发送请求(他在URL中的某个位置,以及正文中的某个位置),借助刷新令牌,用户可以在会话重置或令牌损坏时获得新令牌。授权错误(401)由okhttp3身份验证器处理,我们设法将其与毕加索一起使用。但是有一个问题 - 毕加索如果屏幕上有几张图片 - 连续发送多个请求,同时或几乎同时,并且由于它们都立即收到答案401,如果令牌腐烂,身份验证器立即发送相同数量的更新令牌的请求。有没有一些优雅的方法来等待令牌更新,然后重复对其余图片的请求?现在它发生如下 - 收到错误401后,令牌重置为零(令牌= “”),并且落入身份验证器检查的所有其他流是否(令牌==“”)执行Thread.sleep()我对此非常不满意private Authenticator getAuthenticator() { return (route, response) -> { if (errorCount > 3){ return null; } if (response.request().url().toString().endsWith("/refreshToken")) { Log.d(TAG, "getAuthenticator: " + "refreshToken"); PasswordRepeatActivity.start(context); return null; } if (response.request().url().toString().endsWith("/auth")) { String message = "Попробуйте позже"; try { com.google.gson.Gson gson = Gson.builder().create(); ApiResponse apiError = gson.fromJson(response.body().string(), ApiResponse.class); message = apiError.getMessage(); } catch (Exception e) { e.printStackTrace(); } throw new IOException(message); } String login = spHelper.getCurrentLogin(); Auth auth = spHelper.getAuth(login); String token = auth.getToken(); HttpUrl oldUrl = response.request().url();我正在寻找在第一个错误401之后发送一个刷新令牌的请求并使用所有其他线程等待它的方法,然后使用新令牌发送请求。除了在身份验证器中等待更新的令牌之外,有没有办法以某种方式简化此代码?现在这种方法大约有100行长,每次都需要更改它 - 甚至阅读和保持头脑中的逻辑也成为一个问题。因此,经过一段时间和一些尝试,我使身份验证器的部分在某个锁定对象上同步。现在,一次只有一个线程可以访问身份验证器。因此,如果令牌需要刷新bs - 它将是,并且在刷新所有等待新令牌的线程后,将使用新令牌重复其调用。感谢@Yuri Schimke分享非常有用的信息。
1 回答
RISEBY
TA贡献1856条经验 获得超5个赞
仅使用 OkHttp,你通常需要在应用中处理这种复杂性,无论是在调用之外、身份验证器中还是在主动进行身份验证的拦截器内部。在这些情况下,也不会为您处理并发性。
在这里讨论
https://github.com/square/okhttp/issues/3714#issuecomment-350469364
请确保进行同步刷新调用,因为异步调用可能没有要执行的空闲线程。
@swankjesse的答案是,如果你在拦截器中进行同步调用,那么你就是在捆绑一个线程,但不会死锁,因为它不需要抓取另一个线程,也不会在这段时间内保持锁定。
一些关于类似主题的博客
https://objectpartners.com/2018/06/08/okhttp-authenticator-selectively-reauthorizing-requests/
https://blog.coinbase.com/okhttp-oauth-token-refreshes-b598f55dd3b2
添加回答
举报
0/150
提交
取消
