Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 将所有正在进行的请求放入队列改造和okhttp_Android_Retrofit_Retrofit2_Okhttp - Fatal编程技术网

Android 将所有正在进行的请求放入队列改造和okhttp

Android 将所有正在进行的请求放入队列改造和okhttp,android,retrofit,retrofit2,okhttp,Android,Retrofit,Retrofit2,Okhttp,我正在使用OKHttp的身份验证程序,如果出现401状态错误,它将重试获取新的访问令牌,但我的应用程序必须同时调用多个API,导致数据损坏,因为现有的刷新令牌将在请求时被删除,但另一个API调用方仍然依赖于此令牌来使用。所以我的问题是:当我们得到401错误状态代码时,是否有必要将请求放入队列(或者至少取消)所有其他api请求 这是我的验证器: public Request authenticate(Route route, Response response) throws IOExcepti

我正在使用
OKHttp
身份验证程序
,如果出现
401
状态错误,它将重试获取新的访问令牌,但我的应用程序必须同时调用多个API,导致数据损坏,因为现有的刷新令牌将在请求时被删除,但另一个API调用方仍然依赖于此令牌来使用。所以我的问题是:当我们得到401错误状态代码时,是否有必要将请求放入队列(或者至少取消)所有其他api请求

这是我的验证器:

 public Request authenticate(Route route, Response response) throws IOException {
       // Refresh your access_token using a synchronous api request
          access_token = getNewAccessTokenHere();
                // Add new header to rejected request and retry it
                return response.request().newBuilder()
                        .header("Authorization", "Bearer " + access_token)
                        .build();
            } else {
                ToastUtil.toast("login again");
                return null;
            }

    }

我的目标是让其他api等待第一个请求的响应,并使用新的访问令牌。

您可以使用
调度程序来访问所有飞行中的呼叫并取消它们


我知道这个问题已经很老了,但最近我发现自己也遇到了同样的问题,我找到了一个对我有效的解决方案,我相信它可以在同样的情况下帮助其他人

如所述,将a连接到OkHttp客户端并限制max请求量的解决方案似乎不适用于开箱即用的改造

因此,我的解决方案是同步我自定义的authenticate方法,对我的singleton翻新实例进行并发调用,直到每个线程的authenticate例程完成。这样,具有未经授权响应的第一个调用可以刷新令牌,并通知下一个调用(也得到未经授权的响应),新的访问令牌已经可用

public class MyAuthenticator implements Authenticator {

    private boolean isRefreshed = false;


    // Call when a new request is being made. Concurrent request should call this method to enable the refresh routine
    public void newRequest(){
        isRefreshed = false;
    }

    @Nullable
    @Override
    public synchronized Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException { // Synchronize the method to avoid refreshing thread overlapping
        if (responseCount(response) > 3) {
            return null;
        }

        if (!isRefreshed){
            // Refresh your access_token using a synchronous api request
            String accessToken = getNewAccessTokenHere();

            // Saves the new access token
            saveNewAccessToken(accessToken);
            isRefreshed = true;

            // Add new header to rejected request and retry it
            return response.request().newBuilder()
                .removeHeader("Authorization") // removes the old header, avoiding duplications
                .addHeader("Authorization", "Bearer " + accessToken)
                .build();

        }
        else{ // Access token already refreshed so retry with the new one

            // Get the saved access token
            String accessToken = getAccessToken(); 

            return response.request()
                        .newBuilder()
                        .removeHeader("Authorization")
                        .addHeader("Authorization", accessToken)
                        .build();
    }

}

private int responseCount(Response response) {
    int result = 1;
    while ((response = response.priorResponse()) != null) {
        result++;
    }
    return result;
}

}

我们是否必须将所有其他请求放入队列中,以便稍后重试?另外,我是否可以在authenticator中创建新的调度器,如下所示:
dispatcher dp=new dispatcher()?从何处调用newRequest()?