Ktor Client: мультиплатформенный HTTP
Один сетевой клиент на Kotlin, который под капотом использует родной HTTP-движок каждой платформы.
Ktor Client — мультиплатформенная HTTP-библиотека с архитектурой «общий API + платформенный движок (engine)»: один и тот же код запросов работает поверх OkHttp на Android и Darwin (NSURLSession) на iOS.
Почему именно Ktor
Сетевой слой — первый кандидат на вынос в общий код, и Ktor сделан под это. Его клиент устроен как раз по формуле KMP: общий API в commonMain, а конкретный движок подключается в платформенном наборе. На Android это движок поверх OkHttp, на iOS — Darwin поверх NSURLSession. Ваш код запросов от движка не зависит.
Зависимости по платформам
commonMain: io.ktor:ktor-client-core
io.ktor:ktor-client-content-negotiation
io.ktor:ktor-serialization-kotlinx-json
androidMain: io.ktor:ktor-client-okhttp
iosMain: io.ktor:ktor-client-darwinСоздание клиента в общем коде
// commonMain
val client = HttpClient {
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
}Обратите внимание: создаём HttpClient без явного указания движка — Ktor подберёт тот, что есть в платформенном наборе. Если движков несколько или нужно настроить таймауты, движок передают явно через expect/actual-фабрику.
Запрос как suspend-функция
// commonMain
class OrderApi(private val client: HttpClient) {
suspend fun fetchOrders(): List<OrderDto> =
client.get("https://api.example.com/orders").body()
}Запрос — это suspend-функция: она не блокирует поток, а приостанавливается. Поэтому сеть в KMP неотделима от корутин.
Как работает под капотом
Ktor определяет движок через тот же механизм, что и весь KMP: интерфейс HttpClientEngine в общем коде, конкретные реализации в платформенных артефактах. Когда вы пишете HttpClient { } без аргумента, Ktor через service-loader-подобный механизм находит единственный движок в classpath цели. Это объясняет, почему движок кладут именно в androidMain/iosMain: в общем коде его быть не может, ведь он завязан на платформенный HTTP-стек.
Частые ошибки
Положить движок (например, ktor-client-okhttp) в commonMain — Android соберётся, iOS упадёт, ведь OkHttp это JVM. Движок всегда платформенный. Вторая ошибка — создавать новый HttpClient на каждый запрос: клиент тяжёлый, держите его один на приложение и закрывайте при завершении.
Итоги
- Ktor — «общий API + платформенный движок», идеально ложится на KMP.
- Движок (OkHttp/Darwin) идёт в платформенный набор, не в общий.
- Запросы —
suspend-функции, неразрывно связаны с корутинами. - Клиент создаётся один раз и переиспользуется.