有多种选择可以减少Android应用的网络使用。 很少使用的是If-Modified-Since或Etags头部。 它已经包含在OkHttp3中,你只需要启用它。
想象一下,你的应用程序的朋友列表正在网站上更新,除了在每次应用程序启动时获取朋友列表,还有什么办法获取应用程序的更改? 您可以实现自定义逻辑,也可以启用缓存。
要快速转到客户端实现,请滚动到选择:客户端实现。
If-Modified-Since和Last-Modified
如果在客户端上次请求后没有更改,则使用If-Modified-Since和Last-Modified头部组合,服务器将返回304未修改(NOT MODIFIED)状态。 因为此响应不包含内容正文,它的大小只有几个字节。
工作原理:Last-Modified头部由服务器根据其响应设置,它是客户端请求的资源的最后一个编辑日期。 假设客户端请求一个文章列表,响应的Last-Modified头部将是列表中最近编辑的文章的最后一个编辑日期。
来自服务器的Last-Modified响应头部由客户端在下一个等效呼叫中用作If-Modified-Since请求头。 服务器检查在If-Modified-Since日期之后是否有任何请求的项目更改。 如果没有,它将返回304未修改(NOT MODIFIED)状态。 如果有变化,它将获取并返回完整的结果。 根据后端开发人员如何实现这一点,它可能比使用Etag更快。
Etag和If-None-Match
Etag以类似的方式起作用。 Etags不太容易实现,它需要服务器每次运行完整的查询并且创建哈希。
工作原理:后端开发人员在发送响应之前将创建响应内容和详细信息的哈希(例如使用SHA1),并将其添加为Etag标题。 客户端将根据未来的等效请求将此Etag作为If-None-Match头发送给服务器。 在准备响应时,服务器将根据请求将其新的响应哈希与Etag进行比较。 如果它是一样的,那么服务器将返回304未修改(NOT MODIFIED)状态,而没有内容。 如果它不匹配,那么服务器将进行常规响应,新的Etag作为头部。
摘果实:客户端实现
如果您使用Retrofit2,在客户端启用Last-Modified或Etags是简单的,只是没有写入文档记录罢了。 在创建Retrofit实例地方,打开缓存:
private final static int CACHE_SIZE_BYTES = 1024 * 1024 * 2;
public static Retrofit getAdapter(Context context, String baseUrl) {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.cache(
new Cache(context.getCacheDir(), CACHE_SIZE_BYTES));
Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.baseUrl(baseUrl).client(client);
return retrofitBuilder.build();
}
根据服务器的响应,Last-Modified头部或Etags将被自动使用。 此外,您将希望减少处理/解析时间:
减少处理
在304状态下,Retrofit2和OkHttp3将假设此响应等于最后一个响应; 缓存响应被返回。 要注意304,请查看原始响应代码:
if (response.isSuccessful() &&
response.raw().networkResponse() != null &&
response.raw().networkResponse().code() ==
HttpURLConnection.HTTP_NOT_MODIFIED) {
// not modified, no need to do anything.
return;
}
// parse response here
获取正常(非原始)响应代码将为您提供缓存状态代码,可能为200 OK:
response.networkResponse().code() // NO
在某些情况下,您可能不需要检查HTTP_NOT_MODIFIED。 例如,您可能需要重新解析响应,当要直接从网络显示某些内容时,即使没有更改。
故障排除
当Etag或Last-Modified设置不起作用时:
1. 检查Cache-Control头部
使用Stetho或OkHttp logging interceptor来检查头部。如果它显示如下信息:
Cache-Control: must-revalidate, no-cache, no-store, private // NO
那么服务器的缓存配置是不正确的。 必须启用缓存才能使OkHttp3缓存工作。 一个正确的头部是:
Cache-Control: private, must-revalidate // YES
使用Stetho或记录拦截器还可以看到所有请求和响应的Last-Modified和Etag头部。 仔细检查它们是否存在和正确。
2. 同时使用Etags和Last-Modified
OkHttp3将以严格的顺序检查缓存头部:
1. 如果最后一个响应包含一个ETag头部,则在下一个请求中使用相同的ETag值作为If-None-Match。
2. 如果不满足上一点并且最后一个响应包含Last-Modified头部,则该值在下一个请求中用作If-Modified-Since。
所以如果你同时使用两者,Etag可能会阻止Last-Modified使用。 更多信息:OkHttp的缓存是什么?
次要努力
我曾经看到开发人员试图手动设置和保存If-Modified-Since和If-None-Match头部。 如果您使用Retrofit2和/或OkHttp3,则不需要这些操作。
您需要在客户端和服务器端设置正确的缓存配置才能降低应用程序的网络流量。