OkHttp to wysokowydajny klient HTTP dla Android i Kotlin, opracowany przez firmę Square jako podstawa dla Retrofit i innych bibliotek sieciowych. Zapewnia efektywne zarządzanie połączeniami, wbudowane buforowanie i obsługę HTTP/2. Według danych Square, 2025, OkHttp przetwarza miliardy zapytań dziennie w aplikacjach na całym świecie.
Najważniejsze
OkHttp to wydajny klient HTTP dla Java, Android i Kotlin, opracowany przez firmę Square. Biblioteka udostępnia niskopoziomowe API do wykonywania zapytań HTTP z obsługą HTTP/2, SPDY, WebSocket i automatycznego odtwarzania połączeń w przypadku awarii sieci.
OkHttp pojawił się w 2013 roku jako odpowiedź na potrzebę niezawodnego klienta HTTP, który rozwiązałby problemy HttpURLConnection — brak puli połączeń, słabą obsługę HTTP/2 i niewygodne API. Do 2025 roku OkHttp jest używane na poziomie systemowym Android API: OkHttp jest wbudowane w implementację HttpURLConnection od Androida 4.4 (API 19).
Według danych Google I/O 2024, OkHttp przetwarza ponad 70% wszystkich zapytań HTTP w ekosystemie Androida. Jest to możliwe, ponieważ OkHttp stanowi warstwę transportową dla Retrofit, Apollo GraphQL, Firebase i wielu innych bibliotek. Programiści otrzymują funkcjonalność OkHttp automatycznie, bez jawnego dołączania go.
Architektura OkHttp opiera się na łańcuchu przechwytywaczy (Interceptor chain). Każde zapytanie przechodzi przez sekwencję przechwytywaczy, które mogą modyfikować Request, Response lub przerwać wykonanie. Ta architektura przypomina wzorzec Chain of Responsibility i pozwala elastycznie rozszerzać funkcjonalność.
Gdy aplikacja wysyła zapytanie, OkHttp wykonuje następujące kroki: rozwiązuje DNS, wybiera połączenie z puli (lub tworzy nowe), otwiera uzgadnianie TLS (jeśli HTTPS), wysyła zapytanie HTTP, otrzymuje odpowiedź i zwraca ją do aplikacji. RealCall to wewnętrzna klasa zarządzająca pełnym cyklem życia zapytania od utworzenia do zakończenia.
OkHttp automatycznie obsługuje przekierowania (302, 301), ponawia zapytania w przypadku awarii sieci (retry), stosuje protokół keep-alive i obsługuje przezroczystą kompresję gzip. Programista nie musi pisać kodu dla tych operacji — OkHttp wykonuje je automatycznie na podstawie nagłówków serwera.
HTTP/2 pozwala wysyłać wiele zapytań przez jedno połączenie TCP jednocześnie, bez blokowania (head-of-line blocking, charakterystyczne dla HTTP/1.1). OkHttp automatycznie używa HTTP/2, jeśli serwer obsługuje ten protokół, i przezroczysto przełącza się na HTTP/1.1 w razie potrzeby.
Multipleksowanie HTTP/2 jest szczególnie ważne dla aplikacji mobilnych, gdzie opóźnienie nawiązania połączenia (TCP + TLS) może wynosić 100–300 ms. Zamiast 10 kolejnych połączeń OkHttp używa jednego, zmniejszając całkowite opóźnienie o 40–60% na typowych urządzeniach z Androidem przy niestabilnym połączeniu.
Interceptor to interfejs z jedną metodą intercept(Chain), który otrzymuje Request, wykonuje działania i zwraca Response. Przechwytywacze są dwóch typów: przechwytywacze aplikacyjne (dodawane przez addInterceptor) i sieciowe (addNetworkInterceptor).
Przechwytywacze aplikacyjne uruchamiają się przed utworzeniem zapytania HTTP — widzą oryginalny Request i końcowy Response po wszystkich przekształceniach. Przechwytywacze sieciowe uruchamiają się na poziomie sieci: widzą zapytanie po kompresji gzip, dodaniu nagłówków Content-Length, przekierowaniach i ponownych próbach. Przechwytywacze sieciowe nie są wywoływane, jeśli odpowiedź pochodzi z pamięci podręcznej.
| Typ przechwytywacza | Metoda dodawania | Kiedy wywoływany | Widzi pamięć podręczną |
|---|---|---|---|
| Application Interceptor | addInterceptor() | Przed i po zapytaniu | Tak |
| Network Interceptor | addNetworkInterceptor() | Na poziomie sieci | Nie |
W praktyce przechwytywacze OkHttp rozwiązują trzy główne zadania: autoryzację (dodawanie nagłówka Authorization), logowanie (HttpLoggingInterceptor do debugowania) i ponawianie (automatyczne powtarzanie zapytania przy awariach sieci). Łącząc kilka przechwytywaczy, można zbudować pełny pipeline przetwarzania zapytania bez powielania kodu w każdym wywołaniu HTTP aplikacji.
Kolejność dodawania przechwytywaczy ma znaczenie: Interceptor dodany jako pierwszy wykonuje się jako pierwszy na wejściu i jako ostatni na wyjściu. Dla NetworkInterceptor kolejność jest określana przez stos sieciowy. Zalecana kolejność: AuthInterceptor (dodaje token), LoggingInterceptor (loguje zapytanie), RetryInterceptor (ponawia przy awariach).
Do debugowania zapytań sieciowych używa się HttpLoggingInterceptor — gotowego przechwytywacza od Square. Loguje on metodę, URL, nagłówki i treść zapytania oraz odpowiedzi. Poziomy logowania: BASIC (metoda + URL + kod), HEADERS (z nagłówkami) i BODY (pełne zapytanie i odpowiedź). BODY jest przydatny podczas programowania, ale na produkcji jest wyłączany ze względów bezpieczeństwa i wydajności.
Rozważmy podstawowe zapytanie GET przez OkHttp. Najpierw tworzy się OkHttpClient — ciężki obiekt, który tworzy się raz i ponownie wykorzystuje. Następnie formułuje się Request z URL, a zapytanie jest wykonywane synchronicznie przez execute lub asynchronicznie przez 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())
Do wykonania asynchronicznego używa się metody enqueue, która przyjmuje Callback. OkHttp wykonuje zapytanie w tle i zwraca wynik w callbacku w tym samym wątku. Do przełączenia na główny wątek Androida użyj Handler lub korutyn.
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("Żądanie nie powiodło się: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
Niestandardowy Interceptor dodaje token Bearer do każdego zapytania. Przechwytywacz sprawdza obecność nagłówka Authorization, a jeśli token nie jest jeszcze ustawiony, dodaje go z magazynu. W przypadku odpowiedzi 401 przechwytywacz może odświeżyć token przez 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)
}
}
Pula połączeń (ConnectionPool) — kluczowa optymalizacja OkHttp, umożliwiająca ponowne wykorzystanie połączeń TCP dla wielu zapytań. Zamiast tworzyć nowy gniazdo dla każdego zapytania, OkHttp przechowuje do 5 nieaktywnych połączeń (domyślnie) przez 5 minut, co zmniejsza opóźnienie o 30–70% dla powtarzających się zapytań do tego samego hosta.
Buforowanie odpowiedzi jest realizowane przez klasę Cache. Aby włączyć buforowanie, wystarczy wskazać katalog i maksymalny rozmiar w OkHttpClient.Builder. OkHttp automatycznie buforuje odpowiedzi GET zgodnie z nagłówkami Cache-Control, Expires i ETag, zwracając buforowane dane bez zapytania sieciowego, jeśli nie są nieaktualne.
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()
Prawidłowa konfiguracja puli i bufora jest szczególnie ważna dla aplikacji z częstymi zapytaniami — kanałów informacyjnych, czatów, aktualizacji danych. Bez puli każde połączenie TCP wymaga trójstronnego uzgadniania (SYN, SYN-ACK, ACK) i potencjalnie uzgadniania TLS (2–3 round-trip), co dodaje 100–500 ms do każdego zapytania.
OkHttp obsługuje również WebSocket przez klasę RealWebSocket. Połączenie WebSocket jest nawiązywane przez uzgadnianie HTTP (101 Switching Protocols), a następnie przełącza się na protokół dwukierunkowy. OkHttp automatycznie wysyła pakiety ping w celu utrzymania połączenia przy życiu i ponownie łączy się w przypadku zerwania. WebSocket od OkHttp jest kompatybilny ze standardowymi punktami końcowymi, takimi jak wss://echo.websocket.org.
Tworzenie OkHttpClient dla każdego zapytania — najczęstszy błąd. OkHttpClient zawiera pulę połączeń, pamięć podręczną i pulę wątków. Tworzenie nowej instancji dla każdego zapytania nie tylko marnuje pamięć, ale także pozbawia korzyści z ponownego wykorzystania połączeń. OkHttpClient powinien być singletonem przez kontener DI.
Ignorowanie zamykania Response.body() prowadzi do wycieków zasobów. ResponseBody zawiera InputStream, który należy zamknąć po odczytaniu. Jeśli używane jest body().string() lub body().bytes(), OkHttp zamyka strumień automatycznie, ale przy odczycie body().byteStream() lub body().charStream() wymagane jest jawne wywołanie close() w bloku finally.
Brak obsługi limitu czasu — kolejny problem. Domyślnie OkHttp nie ma limitów czasu (connectTimeout = 10 sekund, readTimeout = 10 sekund, writeTimeout = 10 sekund). Dla aplikacji mobilnych z niestabilnym połączeniem zaleca się ustawienie connectTimeout 15–30 sekund i readTimeout 15–30 sekund, w przeciwnym razie użytkownik będzie czekał zbyt długo przy słabym sygnale.
Często zadawane pytania
OkHttp to niskopoziomowy klient HTTP z ręcznym zarządzaniem Request i Response. Retrofit to wysokopoziomowa nakładka z adnotacjami. OkHttp jest używane jako transport dla Retrofit, ale może działać również samodzielnie bez dodatkowych bibliotek.
OkHttp używa SSLSocketFactory do uzgadniania TLS. Biblioteka obsługuje CertificatePinner do przypinania certyfikatów (Certificate Pinning), TrustManager do niestandardowej walidacji i HostnameVerifier do sprawdzania nazwy hosta względem certyfikatu.
Zapytania synchroniczne zgłaszają IOException w przypadku problemów z siecią. Zapytania asynchroniczne otrzymują wywołanie onFailure z IOException. Dla błędów HTTP (4xx, 5xx) odpowiedź jest uznawana za pomyślną — kod błędu sprawdza się przez response.isSuccessful().
Tak, OkHttp ma wbudowaną obsługę WebSocket przez klasę WebSocket i WebSocketListener. Po nawiązaniu połączenia WebSocket umożliwia wysyłanie i odbieranie wiadomości w czasie rzeczywistym bez ponownych zapytań HTTP.
Wyłącz automatyczne przekierowania przez followRedirects(false) i followSslRedirects(false) w OkHttpClient.Builder. Jest to przydatne, gdy trzeba ręcznie obsłużyć przekierowanie, na przykład w celu wyodrębnienia tokena z URL przekierowania.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również