原文地址,这里java
OkHttp 是笔者在为为 Khan Academy开发这个 Android app时候的必用库之一。OkHttp库自己已经提供了很是优秀的功能配置,可是下面是咱们在实践中总结出来的一些可以有效增长资源利用率的步骤:android
默认状况下,OkHttp并无将包含Cache-Control
头部文件的响应进行缓存。所以你的客户端可能会浪费时间与带宽去重复请求相同的资源,而不是简单地读取初次请求时候的缓存副本。为了保证基于文件系统的响应缓存,应该配置一个com.squareup.okhttp.Cache
实例而且把它传递给OkHttpClient
的setCache
方法。在初始化该Cache
时,须要指定一个File
对象来指代文件目录以及最大的缓存容量。响应会被缓存写入指定的文件夹,若是缓存大小已经超过了文件夹的指定大小,会根据LRU规则来进行筛选。下面是笔者的具体实践:git
// 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
, 或者 10 MB。github
Stetho 是来自于Facebook的一个颇有用的辅助库,可以容许开发者使用 Chrome Developer Tools 来监测Android应用。除了可以容许开发者监测SQLite数据库以及视图层级以外,Stetho还能辅助监测全部的来自OkHttp的网络请求与响应。web
这样的自检方法可以保证服务器返回恰当的带有缓存控制的响应,同时还能监测当缓存资源存在时是否肯定没有请求被发出。若是要使用Stetho,只须要简单地来添加一个StethoInterceptor
实例到网络拦截器中:chrome
okHttpClient.networkInterceptors().add(new StethoInterceptor());
接下来,在应用运行以后,打开Chrome而且跳转到chrome://inspect
界面,既能够看到上述画面。数据库
笔者是直接使用了Picasso进行网络图片的加载,以及使用Retrofit来简化请求构造以及响应解码。默认状况下,这两个库是使用了OkHttpClient进行底层的网络交互。以Picasso的2.5.2版本的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; }
Retrofit有一个很相似的工厂方法。在应用中,图片每每是经常使用的大型资源之一,Picasso自己维护了一个基于LRU规则的缓存系统,是直接在内存中的缓存。服务器
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头文件中的详细的本机信息是每每用来日志记录与分析的重要来源。默认状况下,OkHttp中自带的User-Agent属性会说明OkHttp的版本。若是须要定制本身的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); } }
在构造传入拦截器的具体的User-Agent的值时,咱们使用了以下信息:
Android的版本信息
Build.MODEL
, 或者用户可见的终端产品名
Build.BRAND
Build.VERSION.SDK_INT
BuildConfig.APPLICATION_ID
BuildConfig.VERSION_NAME
BuildConfig.VERSION_CODE
最后三个值是Gradle文件中包含的版本信息。若是你是使用的WebView,则能够直接在WebView中进行构造:
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.