39
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

OkHttp3はシングルトンにすべし

はじめに

OkHttp2とOkHttp3とでコネクションプールの部分が大きく変わっている。
Change Logからの引用。

There is no longer a global singleton connection pool. In OkHttp 2.x, all OkHttpClient instances shared a common connection pool by default. In OkHttp 3.x, each new OkHttpClient gets its own private connection pool. Applications should avoid creating many connection pools as doing so prevents connection reuse. Each connection pool holds its own set of connections alive so applications that have many pools also risk exhausting memory!

上記からわかるように、OkHttp2まではコネクションプールを共有していたのが、OkHttp3からはコネクションプールを各インスタンスごとに別々で持つようになった。
それを知らずにOkHttpを新しくインスタンス生成し続けると、OutOfMemoryErrorになりかねない。
なので、OkHttp3はシングルトンで書くとよい。

サンプルコード

とりあえず、シングルトンで書いてみました。
もっとこうしたほうがいいとかあったらコメントください。

OkHttpSingleton.java

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class OkHttpSingleton {

    private OkHttpClient mOkHttpClient;

    private static OkHttpSingleton ourInstance = new OkHttpSingleton();

    public static OkHttpSingleton getInstance() {
        return ourInstance;
    }

    private OkHttpSingleton() {

        OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
        okHttpBuilder.connectTimeout(20, TimeUnit.SECONDS);
        okHttpBuilder.readTimeout(15, TimeUnit.SECONDS);
        okHttpBuilder.writeTimeout(15, TimeUnit.SECONDS);
        okHttpBuilder.addInterceptor(getInterceptor());

        mOkHttpClient = okHttpBuilder.build();
    }

    private Interceptor getInterceptor() {

        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                Request newRequest = chain.request().newBuilder()
                        .addHeader("Accept", "application/json")
                        .build();

                return chain.proceed(newRequest);
            }
        };
    }

    public OkHttpClient getOkHttpClient() {
        return mOkHttpClient;
    }
}

リクエストヘッダーを共通にする場合は、OkHttpClientのInterceptorを使うとよい。

OkHttpClientの設定(タイムアウト時間など)を個別に変更したい場合は、OkHttpClient.newBuilder()を使って書き換える。


OkHttpClient copy = client.newBuilder()
          .readTimeout(500, TimeUnit.MILLISECONDS)
          .build();

参考

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
39
Help us understand the problem. What are the problem?