عميل HTTP بلغة Kotlin: إجراء الطلبات بشكل صحيح: من الألف إلى الياء
التطوير الحديث بلغة Kotlin لا يمكن تصوره بدون التفاعل الشبكي. سواء كان تطبيق Android أو حل خادم باستخدام Ktor أو تطبيق سطح مكتب - تظل طلبات HTTP الوسيلة الرئيسية لتبادل البيانات. في هذه المقالة، سنشرح كيفية تنظيم عميل HTTP بشكل صحيح بلغة Kotlin، وسنستعرض المكتبات الشائعة وأفضل الممارسات.
لماذا Kotlin مثالية لطلبات HTTP؟
تقدم Kotlin بناء جملة حديثًا، وأمانًا من القيم الخالية، وتوافقًا كاملاً مع نظام Java البيئي. بفضل الكوروتينات وواجهات برمجة التطبيقات التدفقية، يصبح العمل مع الشبكة نظيفًا وغير متزامن. المزايا الرئيسية:
- الكوروتينات - خيوط خفيفة الوزن للعمليات غير المتزامنة دون حظر
- منشئات آمنة من حيث النوع - بناء مريح لطلبات HTTP
- الفئات المختومة - معالجة أنيقة لحالات الرد
- دوال التمديد - توسيع وظائف المكتبات
اختيار عميل HTTP لـ Kotlin
حاليًا، تهيمن ثلاث مكتبات على نظام Kotlin البيئي: OkHttp وKtor Client وRetrofit. سنستعرض كل منها مع أمثلة برمجية.
1. OkHttp - الخيار المثبت عبر الزمن
OkHttp من Square هو عميل HTTP الأكثر شيوعًا لـ JVM. إنه فعال، ويدعم HTTP/2، والضغط التلقائي، والتخزين المؤقت.
// build.gradle.ktsimplementation("com.squareup.okhttp3:okhttp:4.12.0")
// مثال على طلب GET باستخدام OkHttpimport okhttp3.OkHttpClientimport okhttp3.Requestimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.withContext
class OkHttpExample { private val client = OkHttpClient.Builder() .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS) .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS) .build()
suspend fun fetchData(url: String): String = withContext(Dispatchers.IO) { val request = Request.Builder() .url(url) .header("Accept", "application/json") .build()
client.newCall(request).execute().use { response -> if (!response.isSuccessful) { throw RuntimeException("خطأ: ${response.code}") } response.body?.string() ?: throw RuntimeException("رد فارغ") } }}2. Ktor Client - الخيار الأصلي لـ Kotlin
Ktor Client هو جزء من نظام JetBrains البيئي، مكتوب بالكامل بلغة Kotlin مع دعم متعدد المنصات. مثالي لخوادم Ktor ومشاريع Android/iOS.
// build.gradle.ktsimplementation("io.ktor:ktor-client-core:2.3.7")implementation("io.ktor:ktor-client-cio:2.3.7")implementation("io.ktor:ktor-client-content-negotiation:2.3.7")implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
import io.ktor.client.*import io.ktor.client.call.*import io.ktor.client.engine.cio.*import io.ktor.client.plugins.contentnegotiation.*import io.ktor.client.request.*import io.ktor.client.statement.*import io.ktor.serialization.kotlinx.json.*import kotlinx.serialization.Serializable
@Serializabledata class Post(val userId: Int, val id: Int, val title: String, val body: String)
class KtorExample { private val client = HttpClient(CIO) { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true isLenient = true }) } engine { requestTimeout = 30_000 } }
suspend fun getPost(id: Int): Post { val response: HttpResponse = client.get("https://jsonplaceholder.typicode.com/posts/$id") return response.body() }
suspend fun createPost(post: Post): Post { val response: HttpResponse = client.post("https://jsonplaceholder.typicode.com/posts") { setBody(post)