Настройка OkHttp для сетевых запросов в Android-приложении
OkHttp — HTTP-клиент, на котором построены Retrofit, Coil, Glide и большинство Android-библиотек, работающих с сетью. Напрямую OkHttp используют, когда нужен полный контроль: WebSocket-соединения, кастомные протоколы, загрузка файлов с прогрессом, специфическая обработка заголовков — то, что в Retrofit либо невозможно, либо требует обходных путей.
Когда нужен OkHttp напрямую, а не через Retrofit
WebSocket: OkHttpClient.newWebSocket(request, listener) — нативная поддержка без дополнительных зависимостей. WebSocketListener получает колбэки onOpen, onMessage, onFailure, onClosed. Для автоматического реконнекта нужна собственная логика с exponential backoff.
Загрузка и выгрузка файлов с прогрессом. Retrofit позволяет загружать файлы через @Multipart, но отследить прогресс можно только через кастомный RequestBody, который оборачивает источник и вызывает callback при записи байтов. Это OkHttp-уровень.
Кастомная аутентификация. Authenticator интерфейс OkHttp вызывается при 401, позволяет синхронно получить новый токен и повторить запрос. С Retrofit это тоже работает, но через OkHttpClient.
Общий HTTP-клиент для нескольких библиотек. Coil принимает OkHttpClient в ImageLoader.Builder, Retrofit — в Retrofit.Builder. Один настроенный клиент с общим connection pool и кешем — вместо нескольких отдельных клиентов с дублирующейся логикой.
Конфигурация OkHttpClient
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.cache(Cache(cacheDir, 10 * 1024 * 1024)) // 10 MB кеш
.addInterceptor(authInterceptor)
.addInterceptor(loggingInterceptor)
.addNetworkInterceptor(networkMonitorInterceptor)
.authenticator(tokenRefreshAuthenticator)
.connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES))
.build()
addInterceptor vs addNetworkInterceptor: application-интерсепторы вызываются один раз и видят кешированные ответы. Network-интерсепторы — только для реальных сетевых запросов. Для логирования байт трафика — network interceptor. Для добавления заголовков аутентификации — application interceptor.
HTTP-кеш: Cache с правильным cache-dir (обычно context.cacheDir) ускоряет повторные запросы и работает в оффлайн-режиме, если сервер отдаёт Cache-Control заголовки. Если не отдаёт — ForceCacheInterceptor с принудительным FORCE_CACHE для оффлайна.
Certificate pinning: CertificatePinner.Builder().add("api.example.com", "sha256/AAAA...").build(). SHA-256 fingerprint получается из сертификата через openssl x509 -in cert.pem -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64. Pinning ломает соединение при ротации сертификата — нужно заранее добавлять новый fingerprint до смены.
Типичные ошибки
Создание OkHttpClient на каждый запрос. Клиент держит thread pool, connection pool и кеш — это должен быть синглтон. В Hilt — @Singleton в @Provides.
Блокирующие операции внутри Interceptor. Interceptor.intercept() вызывается на OkHttp's dispatcher threads, но если внутри делать suspend-функцию через runBlocking — это блокирует dispatcher thread. Для async операций в интерсепторе (например, refresh токена) используем synchronized блок с условной переменной, или выносим refresh в Authenticator, который синхронный по контракту.
Тестирование: MockWebServer из com.squareup.okhttp3:mockwebserver — стандартный инструмент для unit-тестов сетевого слоя. Поднимает локальный сервер, принимает запросы, возвращает заготовленные ответы.
Настройка OkHttp с интерсепторами, кешем, WebSocket или загрузкой файлов — 1-3 дня. Стоимость рассчитывается индивидуально.







