高性能OkHttp
高性能的OkHttp
OkHttp 是笔者在为为 Khan Academy开发这个 Android app时候的必用库之一。
使用文件系统级别的响应缓存
默认情况下,Cache-Control
头部文件的响应进行缓存。因此你的客户端可能会浪费时间与带宽去重复请求相同的资源,而不是简单地读取初次请求时候的缓存副本。为了保证基于文件系统的响应缓存,应该配置一个com.squareup.okhttp.Cache
实例并且把它传递给OkHttpClient
的setCache
方法。在初始化该Cache
时,需要指定一个File
对象来指代文件目录以及最大的缓存容量。响应会被缓存写入指定的文件夹,如果缓存大小已经超过了文件夹的指定大小,会根据
// Base directory recommended by http://stackoverflow.com/a/32752861/400717.
// Guard against null, which is possible according to
// https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ and
// http://stackoverflow.com/q/4441849/400717.
final @Nullable File baseDir = context.getCacheDir();
if (baseDir != null) {
final File cacheDir = new File(baseDir, "HttpResponseCache");
okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}
其中,我们建议的HTTP_RESPONSE_DISK_CACHE_MAX_SIZE
值为10 * 1024 * 1024
使用Stetho
Stetho 是来自于

这样的自检方法能够保证服务器返回恰当的带有缓存控制的响应,同时还能监测当缓存资源存在时是否确定没有请求被发出。如果要使用StethoInterceptor
实例到网络拦截器中:
okHttpClient.networkInterceptors().add(new StethoInterceptor());
接下来,在应用运行之后,打开chrome://inspect
界面,既可以看到上述画面。
与Picasso 以及Retrofit 混合使用
笔者是直接使用了OkHttpDownloader
为例:
private static OkHttpClient defaultOkHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
final Picasso picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
// The client should inject this instance whenever it is needed, but replace the singleton
// instance just in case.
Picasso.setSingletonInstance(picasso);
定制一个User Agent 拦截器
对于由客户端提供的包含在
public final class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
public UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue =
Preconditions.checkNotNull(userAgentHeaderValue);
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final Request requestWithUserAgent = originalRequest
.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
在构造传入拦截器的具体的
Android 的版本信息Build.MODEL
, 或者用户可见的终端产品名Build.BRAND
Build.VERSION.SDK_INT
BuildConfig.APPLICATION_ID
BuildConfig.VERSION_NAME
BuildConfig.VERSION_CODE
最后三个值是
WebSettings settings = webView.getSettings();
settings.setUserAgentString(userAgentHeaderValue);
明确合理的超时时间
Picasso specifies:
- A connect timeout of 15 seconds.
- A read timeout of 20 seconds.
- A write timeout of 20 seconds.
Whereas Retrofit specifies:
- A connect timeout of 15 seconds.
- A read timeout of 20 seconds.
- No write timeout.