高性能的OkHttp

原文地址,這裏java

OkHttp 是筆者在爲爲 Khan Academy開發這個 Android app時候的必用庫之一。OkHttp庫自己已經提供了很是優秀的功能配置,可是下面是咱們在實踐中總結出來的一些可以有效增長資源利用率的步驟:android

使用文件系統級別的響應緩存

默認狀況下,OkHttp並無將包含Cache-Control頭部文件的響應進行緩存。所以你的客戶端可能會浪費時間與帶寬去重複請求相同的資源,而不是簡單地讀取初次請求時候的緩存副本。爲了保證基於文件系統的響應緩存,應該配置一個com.squareup.okhttp.Cache實例而且把它傳遞給OkHttpClientsetCache方法。在初始化該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

Stetho 是來自於Facebook的一個頗有用的輔助庫,可以容許開發者使用 Chrome Developer Tools 來監測Android應用。除了可以容許開發者監測SQLite數據庫以及視圖層級以外,Stetho還能輔助監測全部的來自OkHttp的網絡請求與響應。web

Image of Stetho

這樣的自檢方法可以保證服務器返回恰當的帶有緩存控制的響應,同時還能監測當緩存資源存在時是否肯定沒有請求被髮出。若是要使用Stetho,只須要簡單地來添加一個StethoInterceptor實例到網絡攔截器中:chrome

okHttpClient.networkInterceptors().add(new StethoInterceptor());

接下來,在應用運行以後,打開Chrome而且跳轉到chrome://inspect界面,既能夠看到上述畫面。數據庫

與Picasso以及Retrofit混合使用

筆者是直接使用了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攔截器

對於由客戶端提供的包含在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.

相關文章
相關標籤/搜索