Az OkHttp egy nagy teljesítményű HTTP-kliens Android és Kotlin számára, amelyet a Square fejlesztett ki a Retrofit és más hálózati könyvtárak alapjaként. Hatékony kapcsolatkezelést, beépített gyorsítótárazást és HTTP/2 támogatást biztosít. A Square, 2025 adatai szerint az OkHttp naponta milliárdnyi kérést dolgoz fel világszerte az alkalmazásokban.
Főbb pontok
OkHttp egy hatékony HTTP-kliens Java, Android és Kotlin számára, amelyet a Square fejlesztett ki. A könyvtár alacsony szintű API-t biztosít HTTP-kérések végrehajtásához HTTP/2, SPDY, WebSocket támogatással és a kapcsolatok automatikus helyreállításával hálózati hibák esetén.
Az OkHttp 2013-ban jelent meg válaszként egy megbízható HTTP-kliens iránti igényre, amely megoldaná a HttpURLConnection problémáit — a kapcsolatpool hiányát, a HTTP/2 gyenge támogatását és a kényelmetlen API-t. 2025-re az OkHttp rendszerszinten van használva az Android API-ban: az OkHttp be van építve a HttpURLConnection implementációjába az Android 4.4 (API 19) óta.
A Google I/O 2024 adatai szerint az OkHttp az Android ökoszisztémában az összes HTTP-kérés több mint 70%-át dolgozza fel. Ez azért lehetséges, mert az OkHttp a szállítási réteg a Retrofit, Apollo GraphQL, Firebase és sok más könyvtár számára. A fejlesztők automatikusan megkapják az OkHttp funkcionalitását anélkül, hogy explicit módon csatlakoztatnák.
Az OkHttp architektúrája egy elfogóláncra (Interceptor chain) épül. Minden kérés áthalad egy elfogósorozaton, amelyek módosíthatják a Request-et, Response-t vagy megszakíthatják a végrehajtást. Ez az architektúra a Chain of Responsibility mintára emlékeztet, és lehetővé teszi a funkcionalitás rugalmas bővítését.
Amikor az alkalmazás kérést küld, az OkHttp a következő lépéseket hajtja végre: feloldja a DNS-t, kiválaszt egy kapcsolatot a poolból (vagy újat hoz létre), megnyitja a TLS kézfogást (ha HTTPS), elküldi a HTTP-kérést, megkapja a választ és visszaadja az alkalmazásnak. A RealCall egy belső osztály, amely a kérés teljes életciklusát kezeli a létrehozástól a befejezésig.
Az OkHttp automatikusan kezeli az átirányításokat (302, 301), megismétli a kéréseket hálózati hibák esetén (retry), követi a keep-alive protokollt és támogatja a transzparens gzip tömörítést. A fejlesztőnek nem kell kódot írnia ezekhez a műveletekhez — az OkHttp automatikusan végrehajtja őket a szerver fejlécei alapján.
HTTP/2 lehetővé teszi több kérés egyidejű küldését egyetlen TCP kapcsolaton keresztül, blokkolás nélkül (head-of-line blocking, ami a HTTP/1.1-re jellemző). Az OkHttp automatikusan HTTP/2-t használ, ha a szerver támogatja ezt a protokollt, és szükség esetén transzparensen vált HTTP/1.1-re.
A HTTP/2 multiplexelés különösen fontos a mobilalkalmazások számára, ahol a kapcsolat létrehozásának késleltetése (TCP + TLS) 100–300 ms lehet. 10 egymást követő kapcsolat helyett az OkHttp egyetlen kapcsolatot használ, ami tipikus, instabil kapcsolattal rendelkező Android eszközökön 40–60%-kal csökkenti a teljes késleltetést.
Interceptor egy interfész egyetlen intercept(Chain) metódussal, amely megkapja a Request-et, végrehajtja a műveleteket és visszaadja a Response-t. Az elfogók két típusúak: alkalmazás-elfogók (addInterceptor-en keresztül hozzáadva) és hálózati elfogók (addNetworkInterceptor).
Az alkalmazás-elfogók a HTTP-kérés kialakítása előtt aktiválódnak — látják az eredeti Request-et és a végső Response-t az összes átalakítás után. A hálózati elfogók hálózati szinten aktiválódnak: látják a kérést a gzip tömörítés, a Content-Length fejlécek hozzáadása, az átirányítások és az újrapróbálkozások után. A hálózati elfogók nem hívódnak meg, ha a válasz a gyorsítótárból származik.
| Elfogó típusa | Hozzáadás módja | Mikor hívódik | Látja a gyorsítótárat |
|---|---|---|---|
| Application Interceptor | addInterceptor() | A kérés előtt és után | Igen |
| Network Interceptor | addNetworkInterceptor() | Hálózati szinten | Nem |
A gyakorlatban az OkHttp elfogói három fő feladatot oldanak meg: hitelesítés (Authorization fejléc hozzáadása), naplózás (HttpLoggingInterceptor hibakereséshez) és újrapróbálkozás (a kérés automatikus megismétlése hálózati hibák esetén). Több elfogó kombinálásával teljes kérésfeldolgozó pipeline építhető fel anélkül, hogy a kódot minden HTTP-hívásban meg kellene ismételni.
Az elfogók hozzáadásának sorrendje számít: az elsőként hozzáadott Interceptor végrehajtása első a bemeneten és utolsó a kimeneten. A NetworkInterceptor esetében a sorrendet a hálózati verem határozza meg. Ajánlott sorrend: AuthInterceptor (hozzáadja a tokent), LoggingInterceptor (naplózza a kérést), RetryInterceptor (megismétli hiba esetén).
A hálózati kérések hibakereséséhez HttpLoggingInterceptor használatos — egy kész elfogó a Square-től. Naplózza a metódust, URL-t, fejléceket és a kérés-válasz törzsét. Naplózási szintek: BASIC (metódus + URL + kód), HEADERS (fejlécekkel) és BODY (teljes kérés és válasz). A BODY hasznos fejlesztés közben, de éles környezetben biztonsági és teljesítménybeli okokból kikapcsolják.
Nézzünk meg egy alapvető GET kérést OkHttp-n keresztül. Először létrehozzuk az OkHttpClient-et — egy nehéz objektumot, amelyet egyszer hozunk létre és újrahasznosítunk. Ezután egy Request-et hozunk létre URL-lel, és a kérést szinkron módon hajtjuk végre execute vagy aszinkron módon enqueue segítségével.
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())
Aszinkron végrehajtáshoz az enqueue metódust használjuk, amely egy Callback-et fogad. Az OkHttp a kérést egy háttérszálon hajtja végre, és az eredményt ugyanazon a szálon adja vissza a callback-ben. Az Android főszálra való átváltáshoz használjon Handler-t vagy korutinokat.
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("A kérés sikertelen: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
Egy egyéni Interceptor Bearer tokent ad minden kéréshez. Az elfogó ellenőrzi az Authorization fejléc jelenlétét, és ha a token még nincs beállítva, hozzáadja a tárolóból. 401-es válasz esetén az elfogó frissítheti a tokent az Authenticator segítségével.
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)
}
}
A kapcsolatpool (ConnectionPool) — az OkHttp kulcsoptimalizálása, amely lehetővé teszi a TCP kapcsolatok újrafelhasználását több kéréshez. Ahelyett, hogy minden kéréshez új socketet hozna létre, az OkHttp legfeljebb 5 inaktív kapcsolatot tárol (alapértelmezés szerint) 5 percig, ami 30–70%-kal csökkenti a késleltetést az ugyanazon gazdagéphez irányuló ismételt kéréseknél.
A válaszok gyorsítótárazása a Cache osztályon keresztül valósul meg. A gyorsítótár engedélyezéséhez elegendő megadni a könyvtárat és a maximális méretet az OkHttpClient.Builder-ben. Az OkHttp automatikusan gyorsítótárazza a GET válaszokat a Cache-Control, Expires és ETag fejlécek szerint, és a gyorsítótárazott adatokat hálózati kérés nélkül adja vissza, ha azok nem jártak le.
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()
A pool és a gyorsítótár helyes beállítása különösen fontos a gyakori kérésekkel rendelkező alkalmazásoknál — hírcsatornák, csevegések, adatfrissítések esetén. Pool nélkül minden TCP kapcsolat háromirányú kézfogást (SYN, SYN-ACK, ACK) és potenciálisan TLS kézfogást (2–3 round-trip) igényel, ami 100–500 ms-ot ad hozzá minden kéréshez.
Az OkHttp támogatja a WebSocket-et is a RealWebSocket osztályon keresztül. A WebSocket kapcsolat HTTP kézfogáson (101 Switching Protocols) keresztül jön létre, majd kétirányú protokollra vált. Az OkHttp automatikusan ping kereteket küld a kapcsolat életben tartásához, és megszakadás esetén újracsatlakozik. Az OkHttp WebSocket-je kompatibilis a szabványos végpontokkal, mint a wss://echo.websocket.org.
OkHttpClient létrehozása minden kéréshez — a leggyakoribb hiba. Az OkHttpClient tartalmazza a kapcsolatpoolt, a gyorsítótárat és a szálpoolt. Minden kéréshez új példány létrehozása nemcsak memóriát pazarol, hanem megfoszt a kapcsolatok újrafelhasználásának előnyétől is. Az OkHttpClient-nek singletonnak kell lennie egy DI konténeren keresztül.
A Response.body() bezárásának figyelmen kívül hagyása erőforrás-szivárgáshoz vezet. A ResponseBody egy InputStream-et tartalmaz, amelyet olvasás után be kell zárni. Ha body().string() vagy body().bytes() használatos, az OkHttp automatikusan bezárja a folyamot, de body().byteStream() vagy body().charStream() olvasásakor explicit close() hívás szükséges a finally blokkban.
Az időtúllépés kezelésének hiánya — egy másik probléma. Alapértelmezés szerint az OkHttp-nak nincsenek időtúllépései (connectTimeout = 10 másodperc, readTimeout = 10 másodperc, writeTimeout = 10 másodperc). Instabil kapcsolattal rendelkező mobilalkalmazások esetén ajánlott a connectTimeout 15–30 másodpercre és a readTimeout 15–30 másodpercre állítása, különben a felhasználó túl sokat vár gyenge jel esetén.
Gyakran ismételt kérdések
OkHttp egy alacsony szintű HTTP-kliens a Request és Response kézi kezelésével. A Retrofit egy magas szintű burkoló annotációkkal. Az OkHttp-t szállításként használják a Retrofit számára, de további könyvtárak nélkül önállóan is működhet.
Az OkHttp SSLSocketFactory-t használ a TLS kézfogáshoz. A könyvtár támogatja a CertificatePinner-t a tanúsítványok rögzítéséhez (Certificate Pinning), a TrustManager-t az egyéni érvényesítéshez és a HostnameVerifier-t a gazdanév tanúsítvány elleni ellenőrzéséhez.
A szinkron kérések IOException-t dobnak hálózati problémák esetén. Az aszinkron kérések onFailure hívást kapnak IOException-nal. A HTTP-hibák (4xx, 5xx) esetén a válasz sikeresnek minősül — a hibakódot a response.isSuccessful() segítségével ellenőrizzük.
Igen, az OkHttp beépített támogatással rendelkezik a WebSocket-hez a WebSocket osztályon és WebSocketListener-en keresztül. A kapcsolat létrejötte után a WebSocket valós idejű üzenetküldést és fogadást tesz lehetővé ismételt HTTP-kérések nélkül.
Tiltsa le az automatikus átirányításokat a followRedirects(false) és followSslRedirects(false) segítségével az OkHttpClient.Builder-ben. Ez akkor hasznos, ha manuálisan kell kezelni az átirányítást, például egy token kinyeréséhez az átirányítási URL-ből.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is