OkHttpは、Retrofitヨ他のネットワークライブラリの基盤としてSquareが開発した、AndroidヨKotlin向けの高パフォーマンスHTTPクライアントです。効率的なコネクション管理、組み込みキャッシュ、HTTP/2サポートを提供します。Square, 2025によると、OkHttpは世界中のアプリケーションで毎日数十億のリクエストを処理しています。
メインポイント
OkHttpは、Squareが開発したJava、AndroidヨKotlin向けの効率的なHTTPクライアントです。このライブラリは、HTTP/2、SPDY、WebSocket、およびネットワーク障害時の自動コネクション回復をサポートするHTTPリクエスト実行用の低レベルAPIを提供します。
OkHttpは2013年に、HttpURLConnectionの問題を解決する信頼性の高いHTTPクライアントの必要性に応えて登場しました — コネクションプールの不備、HTTP/2サポートの弱さ、不便なAPI。2025年までにOkHttpはAndroid APIシステムレベルで使用されています: OkHttpはAndroid 4.4 (API 19)以降、HttpURLConnectionの実装に組み込まれています。
Google I/O 2024によると、OkHttpはAndroidエコシステムの全HTTPリクエストの70%以上を処理しています。これは、OkHttpがRetrofit、Apollo GraphQL、Firebaseヨその他多くのライブラリのトランスポート層として機能するためです。開発者は明示的に追加しなくても、OkHttpの機能を自動的に利用できます。
OkHttpのアーキテクチャは、インターセプタチェーンに基づいています。各リクエストは、リクエストヨレスポンスを変更できるインターセプタの連続を通過します。このアーキテクチャは、Chain of Responsibilityパターンに類似しており、柔軟な拡張性を可能にします。
アプリケーションがリクエストを送信すると、OkHttpは次のステップを実行します: DNSを解決し、プールからコネクションを選択し、TLSハンドシェークを開き、HTTPリクエストを送信し、レスポンスを受信し、アプリケーションに戻します。RealCallは、リクエストの作成から完了までの全ライフサイクルを管理する内部クラスです。
OkHttpは、リダイレクト(302、301)を自動的に処理し、ネットワーク障害時にリクエストを再実行し、keep-aliveプロトコルに従い、透明なgzip圧縮をサポートします。開発者がこれらの操作のためにコードを書く必要はありません — OkHttpがサーバーヘッダーに基づいて自動的に実行します。
HTTP/2は、ヘッドオブラインブロッキング(HTTP/1.1の特徴)なしで、単1つのTCPコネクションを通じて一度に複数のリクエストを送信できます。OkHttpは、サーバーがサポートしていれば自動的にHTTP/2を使用し、必要に応じてHTTP/1.1にフォールバックします。
HTTP/2のマルチプレックスは、コネクション構築レイテンシ(TCP + TLS)が100–300ミリ秒になる可能性があるモバイルアプリケーションで特に重要です。10つの並列コネクションの代わりに、OkHttpは1つを使用し、不安定なコネクションのAndroidデバイスで総レイテンシを40–60%削減します。
Interceptorは、単1つのメソッドintercept(Chain)をもつインタフェースで、リクエストを受け取り、処理を実行し、レスポンスを戻します。インターセプタには、アプリケーションインターセプタ(addInterceptorで追加)ヨネットワークインターセプタ(addNetworkInterceptor)の2種類があります。
アプリケーションインターセプタは、HTTPリクエストが構築される前に発火します — 原本のリクエストヨ、すべての変換後の最終レスポンスを確認できます。ネットワークインターセプタはネットワークレベルで発火します: gzip圧縮、Content-Lengthヘッダーの追加、リダイレクトヨ再実行後のリクエストを確認できます。レスポンスがキャッシュから提供された場合、ネットワークインターセプタは呼び出されません。
| インターセプタの種類 | 追加方法 | 呼び出されるタイミング | キャッシュを見る |
|---|---|---|---|
| Application Interceptor | addInterceptor() | リクエストの前後 | はい |
| Network Interceptor | addNetworkInterceptor() | ネットワークレベル | いいえ |
実際には、OkHttpのインターセプタは主な3つのタスクを解決します: 認証(Authorizationヘッダーの追加)、ログ(HttpLoggingInterceptorによるデバッグ)、再実行(ネットワーク障害時の自動リクエスト再実行)。複数のインターセプタを組み合わせることで、アプリケーションの各HTTPコールでコードを複製することなく、完全なリクエスト処理パイプラインを構築できます。
インターセプタを追加する順序は重要です: 最初に追加されたInterceptorは、入力時に最初に実行され、出力時に最後に実行されます。NetworkInterceptorの場合、順序はネットワークスタックによって決定されます。推奨される順序: AuthInterceptor(トークンを追加)、LoggingInterceptor(リクエストをログ)、RetryInterceptor(障害時に再実行)。
ネットワークリクエストをデバッグするには、HttpLoggingInterceptorが使用されます — Squareによる完成したインターセプタです。メソッド、URL、ヘッダー、リクエストヨレスポンスボディをログに記録します。ロギングレベル: BASIC(メソッド + URL + コード)、HEADERS(ヘッダー付き)、BODY(完全なリクエストヨレスポンス)。BODYは開発中に便利ですが、セキュリティヨパフォーマンスの理由からプロダクションでは無効にされます。
OkHttpを使った基本的なGETリクエストを見てみましょう。まず、OkHttpClientが作成されます — 一度作成されて再利用される重いオブジェクトです。次にURLをもつRequestが構築され、executeを通じて同期的に、またはenqueueを通じて非同期的に実行されます。
val client = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build()
val request = Request.Builder()
.url("https://api.github.com/users/octocat")
.header("Accept", "application/vnd.github.v3+json")
.build()
val response = client.newCall(request).execute()
println(response.body()?.string())
非同期実行には、Callbackを受け入れるenqueueメソッドが使用されます。OkHttpはバックグラウンドスレッドでリクエストを実行し、結果を同じスレッドのコールバックに戻します。Androidのメインスレッドに切り替えるには、Handlerまたはコルーチンを使用します。
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("リクエストに失敗しました: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
カスタムInterceptorが、各リクエストにBearerトークンを追加します。インターセプタは、Authorizationヘッダーの存在を確認し、トークンがまだ設定されていなければ、ストレッジから追加します。401レスポンスの場合、インターセプタはAuthenticatorを通じてトークンをリフレッシュできます。
class AuthInterceptor(
private val tokenProvider: () -> String?
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val token = tokenProvider.invoke()
val request = originalRequest.newBuilder()
.header("Authorization", "Bearer $token")
.build()
return chain.proceed(request)
}
}
コネクションプール(ConnectionPool)は、複数のリクエストでTCPコネクションを再利用できるOkHttpの主要な最適化機能です。各リクエストに新しいソケットを作成する代わりに、OkHttpはデフォルトで最大5つの非活動コネクションを5分間保存し、同じホストへの繰り返しリクエストのレイテンシを30–70%削減します。
レスポンスのキャッシュは、Cacheクラスを通じて実装されます。キャッシュを有効にするには、OkHttpClient.Builderでディレクトリヨ最大サイズを指定するだけです。OkHttpは、Cache-Control、Expires、ETagヘッダーに従ってGETレスポンスを自動的にキャッシュし、古くない場合はネットワークリクエストなしでキャッシュされたデータを戻します。
val cacheDir = File(context.cacheDir, "http-cache")
val cache = Cache(cacheDir, 10L * 1024 * 1024)
val client = OkHttpClient.Builder()
.cache(cache)
.connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES))
.build()
プールヨキャッシュの適切な設定は、頻繁にリクエストを行うアプリケーション(ニュースフィード、チャット、データ更新)で特に重要です。プールがない場合、各TCPコネクションは3ウェイハンドシェーク(SYN、SYN-ACK、ACK)ヨ可能なTLSハンドシェーク(2–3ラウンドトリップ)が必要となり、各リクエストに100–500ミリ秒が追加されます。
OkHttpは、RealWebSocketクラスを通じてWebSocketもサポートしています。WebSocketコネクションは、HTTPハンドシェーク(101 Switching Protocols)によって確立され、その後双方向プロトコルに切り替わります。OkHttpはコネクションを維持するために自動的にpingフレームを送信し、切断時に再コネクトします。OkHttpのWebSocketは、wss://echo.websocket.orgなどの標準エンドポイントと互換性があります。
リクエストごとにOkHttpClientを作成することが、もっとも普及した資財です。OkHttpClientには、コネクションプール、キャッシュ、スレッドプールが含まれています。リクエストごとに新しいインスタンスを作成すると、メモリが無駄に消耗されるだけでなく、コネクション再利用のメリットも失われます。OkHttpClientは、DIコンテナを通じてシングルトンにする必要があります。
Response.body()のクローズを忘れると、リソースリークが発生します。ResponseBodyには、読み取り後にクローズする必要があるInputStreamが含まれています。body().string()またはbody().bytes()を使用した場合、OkHttpが自動的にストリームをクローズしますが、body().byteStream()またはbody().charStream()を読む場合は、finallyブロックでclose()を明示的に呼び出す必要があります。
タイムアウト処理の不備ももうひとつの問題です。デフォルトでは、OkHttpのconnectTimeoutは10秒、readTimeoutは10秒、writeTimeoutは10秒です。不安定なコネクションのモバイルアプリケーションでは、connectTimeoutを15–30秒、readTimeoutを15–30秒に設定することをおすすめします。これを行わなければ、信号状態が悪い場合にユーザーが長時間待たされます。
よくある質問
OkHttpは、RequestヨResponseを手動で管理する低レベルHTTPクライアントです。Retrofitは、注釈を使用した高レベルの抽象化です。OkHttpはRetrofitのトランスポート層として使用されますが、追加のライブラリなしで単独で動作することもできます。
OkHttpは、TLSハンドシェークにSSLSocketFactoryを使用します。このライブラリは、証明書ピンニング用のCertificatePinner、カスタム検証用のTrustManager、および証明書に対するホスト名を検証するHostnameVerifierをサポートしています。
同期リクエストは、ネットワーク問題が起きた場合にIOExceptionをスローします。非同期リクエストは、IOExceptionをもつonFailureコールを受け取ります。HTTPエラー(4xx、5xx)の場合、レスポンスは成功とみなされます — エラーコードはresponse.isSuccessful()で確認します。
はい、OkHttpにはWebSocketクラスヨWebSocketListenerを通じた組み込みのWebSocketサポートがあります。コネクション確立後、WebSocketは繰り返しHTTPリクエストなしでリアルタイムにメッセージを送信ヨ受信できます。
OkHttpClient.BuilderでfollowRedirects(false)ヨfollowSslRedirects(false)を使用して自動リダイレクトを無効にします。これは、リダイレクトURLからトークンを抽出する等、リダイレクトを手動で処理したい場合に便利です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。