OkHttp este un client HTTP de înaltă performanță pentru Android și Kotlin, dezvoltat de compania Square ca bază pentru Retrofit și alte biblioteci de rețea. Acesta asigură gestionarea eficientă a conexiunilor, memorarea în cache încorporată și suport pentru HTTP/2. Conform datelor Square, 2025, OkHttp procesează miliarde de cereri zilnic în aplicații din întreaga lume.
Principalele puncte
OkHttp este un client HTTP eficient pentru Java, Android și Kotlin, dezvoltat de compania Square. Biblioteca oferă o API de nivel scăzut pentru executarea cererilor HTTP cu suport pentru HTTP/2, SPDY, WebSocket și restabilirea automată a conexiunilor în cazul defecțiunilor de rețea.
OkHttp a apărut în 2013 ca răspuns la necesitatea unui client HTTP fiabil care să rezolve problemele HttpURLConnection — lipsa pool-ului de conexiuni, suportul slab pentru HTTP/2 și API-ul incomod. Până în 2025, OkHttp este utilizat la nivel de sistem Android API: OkHttp este încorporat în implementarea HttpURLConnection începând cu Android 4.4 (API 19).
Conform datelor Google I/O 2024, OkHttp procesează peste 70% din toate cererile HTTP din ecosistemul Android. Acest lucru este posibil deoarece OkHttp este stratul de transport pentru Retrofit, Apollo GraphQL, Firebase și multe alte biblioteci. Dezvoltatorii primesc funcționalitatea OkHttp automat, fără a-l conecta explicit.
Arhitectura OkHttp este construită pe un lanț de interceptoare (Interceptor chain). Fiecare cerere trece printr-o succesiune de interceptoare care pot modifica Request, Response sau pot întrerupe execuția. Această arhitectură amintește de modelul Chain of Responsibility și permite extinderea flexibilă a funcționalității.
Când aplicația trimite o cerere, OkHttp execută următorii pași: rezolvă DNS, selectează o conexiune din pool (sau creează una nouă), deschide strângerea de mână TLS (dacă este HTTPS), trimite cererea HTTP, primește răspunsul și îl returnează aplicației. RealCall este o clasă internă care gestionează ciclul de viață complet al cererii, de la creare până la finalizare.
OkHttp gestionează automat redirecționările (302, 301), reîncearcă cererile în cazul defecțiunilor de rețea (retry), urmează protocolul keep-alive și suportă compresia transparentă gzip. Dezvoltatorul nu trebuie să scrie cod pentru aceste operații — OkHttp le face automat pe baza antetelor serverului.
HTTP/2 permite trimiterea mai multor cereri printr-o singură conexiune TCP simultan, fără blocare (head-of-line blocking, specifică HTTP/1.1). OkHttp folosește automat HTTP/2 dacă serverul suportă acest protocol și comută transparent la HTTP/1.1 atunci când este necesar.
Multiplexarea HTTP/2 este deosebit de importantă pentru aplicațiile mobile, unde întârzierea stabilirii conexiunii (TCP + TLS) poate fi de 100–300 ms. În loc de 10 conexiuni succesive, OkHttp folosește una singură, reducând întârzierea totală cu 40–60% pe dispozitivele Android tipice cu conexiune instabilă.
Interceptor este o interfață cu o singură metodă intercept(Chain) care primește Request, execută acțiuni și returnează Response. Interceptoarele sunt de două tipuri: interceptoare de aplicație (adăugate prin addInterceptor) și interceptoare de rețea (addNetworkInterceptor).
Interceptoarele de aplicație se activează înainte de formarea cererii HTTP — ele văd Request-ul original și Response-ul final după toate transformările. Interceptoarele de rețea se activează la nivel de rețea: ele văd cererea după compresia gzip, adăugarea antetelor Content-Length, redirecționări și reîncercări. Interceptoarele de rețea nu sunt apelate dacă răspunsul este obținut din cache.
| Tip interceptor | Metodă de adăugare | Când este apelat | Vede cache-ul |
|---|---|---|---|
| Application Interceptor | addInterceptor() | Înainte și după cerere | Da |
| Network Interceptor | addNetworkInterceptor() | La nivel de rețea | Nu |
În practică, interceptoarele OkHttp rezolvă trei sarcini principale: autorizare (adăugarea antetului Authorization), logare (HttpLoggingInterceptor pentru depanare) și reîncercare (repetarea automată a cererii la defecțiuni de rețea). Combinând mai multe interceptoare, se poate construi un pipeline complet de procesare a cererii fără duplicarea codului în fiecare apel HTTP al aplicației.
Ordinea de adăugare a interceptoarelor contează: Interceptorul adăugat primul se execută primul la intrare și ultimul la ieșire. Pentru NetworkInterceptor, ordinea este determinată de stiva de rețea. Ordinea recomandată: AuthInterceptor (adaugă token), LoggingInterceptor (loghează cererea), RetryInterceptor (reîncearcă la defecțiuni).
Pentru depanarea cererilor de rețea se folosește HttpLoggingInterceptor — un interceptor gata făcut de la Square. Acesta loghează metoda, URL-ul, antetele și corpul cererii și răspunsului. Niveluri de logare: BASIC (metodă + URL + cod), HEADERS (cu antete) și BODY (cerere și răspuns complete). BODY este util în timpul dezvoltării, dar în producție este dezactivat din motive de securitate și performanță.
Să examinăm cererea GET de bază prin OkHttp. Mai întâi se creează OkHttpClient — un obiect greu care se creează o dată și se reutilizează. Apoi se formează Request cu URL, iar cererea se execută sincron prin execute sau asincron prin 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())
Pentru executarea asincronă se folosește metoda enqueue, care primește un Callback. OkHttp execută cererea într-un fir de execuție de fundal și returnează rezultatul în callback pe același fir. Pentru comutarea pe firul principal Android, utilizați Handler sau corutine.
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("Cererea a eșuat: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
Un Interceptor personalizat adaugă un token Bearer la fiecare cerere. Interceptorul verifică prezența antetului Authorization și, dacă tokenul nu este încă setat, îl adaugă din stocare. La răspunsul 401, interceptorul poate actualiza tokenul prin 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)
}
}
Pool-ul de conexiuni (ConnectionPool) — optimizarea cheie a OkHttp, care permite reutilizarea conexiunilor TCP pentru mai multe cereri. În loc să creeze un nou socket pentru fiecare cerere, OkHttp stochează până la 5 conexiuni inactive (implicit) timp de 5 minute, ceea ce reduce întârzierea cu 30–70% pentru cererile repetate către același gazdă.
Memorarea în cache a răspunsurilor se implementează prin clasa Cache. Pentru activarea cache-ului, este suficient să specificați directorul și dimensiunea maximă în OkHttpClient.Builder. OkHttp memorează automat răspunsurile GET conform antetelor Cache-Control, Expires și ETag, returnând datele stocate în cache fără cerere de rețea, dacă nu sunt expirate.
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()
Configurarea corectă a pool-ului și cache-ului este deosebit de importantă pentru aplicațiile cu cereri frecvente — fluxuri de știri, chat-uri, actualizări de date. Fără pool, fiecare conexiune TCP necesită o strângere de mână în trei pași (SYN, SYN-ACK, ACK) și potențial o strângere de mână TLS (2–3 round-trip), ceea ce adaugă 100–500 ms la fiecare cerere.
OkHttp suportă și WebSocket prin clasa RealWebSocket. Conexiunea WebSocket se stabilește printr-o strângere de mână HTTP (101 Switching Protocols) și apoi comută la un protocol bidirecțional. OkHttp trimite automat cadre ping pentru a menține conexiunea activă și se reconectează la întrerupere. WebSocket de la OkHttp este compatibil cu endpoint-uri standard precum wss://echo.websocket.org.
Crearea OkHttpClient pentru fiecare cerere — cea mai frecventă greșeală. OkHttpClient conține pool-ul de conexiuni, cache-ul și pool-ul de fire de execuție. Crearea unei noi instanțe pentru fiecare cerere nu doar că risipește memorie, dar și privează de avantajul reutilizării conexiunilor. OkHttpClient trebuie să fie un singleton prin containerul DI.
Ignorarea închiderii Response.body() duce la scurgeri de resurse. ResponseBody conține un InputStream care trebuie închis după citire. Dacă se folosește body().string() sau body().bytes(), OkHttp închide fluxul automat, dar la citirea body().byteStream() sau body().charStream() este necesară apelarea explicită a close() în blocul finally.
Lipsa gestionării timeout-ului — o altă problemă. În mod implicit, OkHttp nu are timeout-uri (connectTimeout = 10 secunde, readTimeout = 10 secunde, writeTimeout = 10 secunde). Pentru aplicațiile mobile cu conexiune instabilă, se recomandă setarea connectTimeout la 15–30 secunde și readTimeout la 15–30 secunde, altfel utilizatorul va aștepta prea mult la semnal slab.
Întrebări frecvente
OkHttp este un client HTTP de nivel scăzut cu gestionare manuală a Request și Response. Retrofit este un înveliș de nivel înalt cu adnotări. OkHttp este utilizat ca transport pentru Retrofit, dar poate funcționa și independent fără biblioteci suplimentare.
OkHttp folosește SSLSocketFactory pentru strângerea de mână TLS. Biblioteca suportă CertificatePinner pentru fixarea certificatelor (Certificate Pinning), TrustManager pentru validare personalizată și HostnameVerifier pentru verificarea numelui gazdei față de certificat.
Cererile sincrone aruncă IOException la probleme de rețea. Cererile asincrone primesc apelul onFailure cu IOException. Pentru erorile HTTP (4xx, 5xx), răspunsul este considerat reușit — codul de eroare se verifică prin response.isSuccessful().
Da, OkHttp are suport încorporat pentru WebSocket prin clasele WebSocket și WebSocketListener. După stabilirea conexiunii, WebSocket permite trimiterea și primirea de mesaje în timp real fără cereri HTTP repetate.
Dezactivați redirecționările automate prin followRedirects(false) și followSslRedirects(false) în OkHttpClient.Builder. Acest lucru este util când trebuie să gestionați manual redirecționarea, de exemplu, pentru a extrage un token din URL-ul de redirecționare.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și