我想以这样一种方式设计 API 调用,以便从一个地方轻松处理成功和失败响应(而不是为所有 API 编写相同的调用函数代码)
以下是我想考虑的场景。
我目前的实现不满足上述要求。有没有办法使用 Retrofit 实现满足上述要求的 API 调用?请为我推荐一个好的设计。
这是我目前的实现:
接口接口.java
public interface ApiInterface {
// Get Devices
@GET("https://example-base-url.com" + "/devices")
Call<ResponseBody> getDevices(@Header("Authorization) String token);
// Other APIs......
}
Run Code Online (Sandbox Code Playgroud)
客户端程序
public class ApiClient {
private static Retrofit retrofitClient = null;
static Retrofit getClient(Context context) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), systemDefaultTrustManager())
.connectTimeout(15, TimeUnit.SECONDS) …Run Code Online (Sandbox Code Playgroud) 我想在访问令牌过期时刷新它。我已经实现了 Authenticator,如下所示:
@Singleton
class TokenAuthenticator(
val authService: Lazy<AuthService>,
private val sharedPreferences: SharedPreferences
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
return authRequestWithNewToken(response.request)
}
private fun authRequestWithNewToken(
request: Request
): Request? {
getFreshAccessToken()?.let { freshToken ->
return getNewRequest(request, freshToken)
}
return null
}
private fun getFreshAccessToken(): String? {
val refreshResponse = authService.get().refreshTokenTemp().execute()
if (refreshResponse.isSuccessful) {
val updatedAccessToken =
refreshResponse.body()?.data?.accessToken ?: return null
val updatedRefreshToken =
refreshResponse.body()?.data?.refreshToken ?: return null
updateToken(updatedAccessToken, updatedRefreshToken)
Timber.tag("TOKEN")
.d("Auth Updated token\n AccessToken: $updatedAccessToken …Run Code Online (Sandbox Code Playgroud) 我想将响应从服务器更改为 423 -> 401,然后使用 Authenticator 调用 refreshToken。
但是为什么 在我的情况下不调用该方法Authenticator.authenticate(Route route, Response response) ?
OkHttp客户端
OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
//Adding token to request
Request request = chain.request();
Request.Builder builder = request.newBuilder();
builder.header("Authorization", "access_token");
return chain.proceed(builder.build());
}
})
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
//changing response code from server 423 -> 401
Request request = …Run Code Online (Sandbox Code Playgroud) 我有一个api,在验证后返回此信息
"token_type":"Bearer",
"expires_in":86400,
"access_token":"XXXXXXXXX",
"refresh_token":"XXXXXXXXXXX"
Run Code Online (Sandbox Code Playgroud)
我已经成功地在sqlite数据库中保存了访问令牌,刷新令牌和expires_in.如何检查令牌是否已过期?这是我到目前为止所拥有的
if(new Date().after(expiresAt)){
Toast.makeText(this, "Token expired", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "You still have time", Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
expiresAt包含expires_in值