改进ETAG和缓存

AAv*_*rin 14 etag android retrofit okhttp

是否有关于如何向Retrofit + OkHttp 添加缓存和ETAG/ If-None-Match支持的正确解释?我正在努力为Etag2个项目添加支持,起初我怀疑HTTP标头可能存在问题,另一个项目已正确设置,缓存仍无法按预期工作.

以下是我试图让它发挥作用.结果显示缓存似乎在应用程序的同一个实例中工作,但是一旦我重新启动 - 所有内容都会再次加载.此外,在我的日志中,我没有看到If-None-Match被添加到请求中,因此我假设服务器不知道ETag并且仍然完全重新计算响应.

以下是一些代码示例:

public class RetrofitHttpClient extends UrlConnectionClient
{

    private OkUrlFactory generateDefaultOkUrlFactory()
    {
        OkHttpClient client = new com.squareup.okhttp.OkHttpClient();

        try
        {
            Cache responseCache = new Cache(baseContext.getCacheDir(), SIZE_OF_CACHE);
            client.setCache(responseCache);
        }
        catch (Exception e)
        {
            Logger.log(this, e, "Unable to set http cache");
        }

        client.setConnectTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
        client.setReadTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);
        return new OkUrlFactory(client);
    }

    private final OkUrlFactory factory;

    public RetrofitHttpClient()
    {
        factory = generateDefaultOkUrlFactory();
    }

    @Override
    protected HttpURLConnection openConnection(retrofit.client.Request request) throws IOException
    {
        return factory.open(new URL(request.getUrl()));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用FULL日志级别和自定义标记创建Rest适配器:

restAdapter = new RestAdapter.Builder()
        .setClient(new RetrofitHttpClient())
        .setEndpoint(Config.BASE_URL)
        .setRequestInterceptor(new SignatureSetter())
        .setConverter(new JacksonConverter(JsonHelper.getObjectMapper()))
        .setLogLevel(RestAdapter.LogLevel.FULL)
        .setLog(new AndroidLog("=NETWORK="))
        .build();
Run Code Online (Sandbox Code Playgroud)

我在应用程序的第一个屏幕上有一个很长的请求进行测试.当我打开应用程序时 - 完成请求需要7秒钟.如果我暂停并恢复应用程序 - 同样的请求需要250毫秒,显然是在缓存中.如果我完全关闭应用程序并重新启动 - 它再次需要7秒钟.

更新:正如所建议的,我使用了自定义的Retrofit构建并附加了一个LoggingInterceptor.这就是我得到的.

Received response for *** in 449,3ms
Date: Wed, 07 Jan 2015 09:02:23 GMT
Server: Apache
X-Powered-By: PHP/5.4.31
Access-Control-Allow-Credentials: true
Pragma:
Cache-Control: public, max-age=3600
X-Frame-Options: SAMEORIGIN
Etag: "hLxLRYztkinJAB453nRV7ncBSuU=-gzip"
Last-Modified: Wed, 24 Dec 2014 13:09:04 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1420621288104
OkHttp-Received-Millis: 1420621288554


Sending request **** on Connection{****:80, proxy=DIRECT@ hostAddress=**** cipherSuite=none protocol=http/1.1}
Accept: application/json;
Host: ****
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/2.2.0

Response is equal to described above
Run Code Online (Sandbox Code Playgroud)

如您所见,If-None-Match下一个请求中不存在标头.

AAv*_*rin 5

我看到这个问题一直引起人们的注意,一旦没有真正的答案我可以选择 - 我正在提供关于这个主题的调查并暂时关闭线程.

调查的最终结果以及GitHub上的改造和okhttp线程中的一些讨论是,OkHttp中存在一个问题,可能会阻止为传出请求设置If-None-Match标记.

该问题应该在OkHttp 2.3中修复,我在这里使用'假设',因为我还没有测试它是否真的有效.测试很困难,因为我使用的是Retrofit,并且必须更新Retrofit以使用新版本的OkHttp并添加一些新的Interceptors支持,以便能够调试OkHttp设置的所有头文件.相关主题在这里:https://github.com/square/okhttp/issues/831

我不确定之后是否更新了Retrofit.希望它是,所以很有可能问题已经解决,Etag应该正常工作 - 只要确保你有最新版本的Retrofit和OkHttp.

一旦我有时间,我会尝试自己测试一切.