使用 Retrofit 时重试机制的最佳实践是什么?

What is the best practices for retry mechanism while using Retrofit?

问题陈述:

我在我的应用程序中使用 Retrofit 进行 API 调用。目前我有 20 多个 Retrofit 接口,具有不同的 Callbacks。目前,当应用程序在这些接口中的任何一个(比如 UpdateUserAPI)中接收到 INVALID_SESSION_ID 时,我必须通过调用 AccessTokenAPI.

来获得新的 ACCESS_TOKEN

建议方法:

当应用在 UpdateUserAPI 中的 Callback 中接收到 INVALID_SESSION_ID 时,调用 AccessTokenAPI 以获取新的 ACCESS_TOKEN。在接收到新的 ACCESS_TOKEN 后,post 与新的 ACCESS_TOKEN 的实际调用(初始参数在 UpdateUserAPI 中)。但这需要在实现UpdateUserAPI的class中保存参数。此外,我只需要重试一次 ACCESS_TOKEN,这应该被处理。

实现上述要求的最佳方法是什么?

创建您自己的 TokenInterceptor

public class TokenInterceptor implements Interceptor 

然后设置为你的okktpclient

Interceptor tokenInterceptor = new TokenInterceptor(provideUserLoginDao(appDatabase));
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(tokenInterceptor)
                .writeTimeout(50, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();

此 post 中的有用信息还有:Refreshing OAuth token using Retrofit without modifying all calls

创建您自己的自定义拦截器并检查您的 token/session_id 是否有效。如果您的 session_id 已过期,然后点击您的 updateUserAPI 以获取新 ID 并将此 ID 设置在 header 或您想要的位置。这是一些代码示例。

RefreshTokenInterceptor

    public static class RInterceptor implements Interceptor {
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        try {
            if (response.code() == 410) {

                Response r = null;
                try {

                    r = makeTokenRefreshCall(request, chain);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return r;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return response;
    }
}


  private static Response makeTokenRefreshCall(Request req, Interceptor.Chain chain) throws JSONException, IOException {
    /* fetch refreshed token, some synchronous API call, whatever Because we are responsible to return new response  */
    refreshTokenSync();
    Request newRequest;
    newRequest = req.newBuilder().header("authorization", NEW_TOKEN)/*.post(req.body())*/.build();
    return chain.proceed(newRequest);


}

RESTClient

 OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .readTimeout(50, TimeUnit.SECONDS)
                    .writeTimeout(55, TimeUnit.SECONDS)
                    .connectTimeout(50, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                   .addInterceptor(new NetworkInterceptor())
                    .build();