Dio: ما هو وميزات عميل HTTP لتطبيقات Flutter

المؤلف: IT Sectr نُشر: 2026-03-07 وقت القراءة: 8 دق

Dio هو عميل HTTP قوي لـ Dart و Flutter، تم تطويره بواسطة المهندس الصيني Wenda Wang. توفر المكتبة API متقدمة مع دعم للمعترضات و FormData وتحميل الملفات وإلغاء الطلبات. وفقًا لـ pub.dev, 2025، Dio هو عميل HTTP الأكثر شعبية في نظام Flutter البيئي مع أكثر من 8 آلاف نجمة على GitHub.

الملامح الرئيسية

  • Dio — عميل HTTP قوي لـ Dart و Flutter مع معترضات ومحولات
  • المعترضات — آلية اعتراض الطلبات والاستجابات والأخطاء للتسجيل والترخيص
  • FormData — دعم مدمج لـ multipart/form-data لتحميل الملفات
  • إلغاء الطلبات — CancelToken يسمح بإيقاف الطلبات الجارية في أي وقت
  • المحولات — تحويل مخصص للبيانات قبل الإرسال وبعد الاستلام

ما هو Dio؟

Dio هي مكتبة عميل HTTP قوية للغة Dart، الأكثر استخدامًا في تطبيقات Flutter. توفر Dio API غنية مع دعم للمعترضات والتكوين العام والمحولات و FormData وتحميل الملفات وإدارة المهلات بمرونة، مما يجعلها الخيار الأساسي للاتصال بالشبكة في مجتمع Flutter.

تم إنشاء المكتبة بواسطة Wenda Wang في عام 2018 كبديل لـ HttpClient المدمج في dart:io، الذي كان يفتقر إلى العديد من الإمكانيات الحديثة: تكوين موحد لجميع الطلبات ومعترضات وتسلسل تلقائي. بحلول عام 2025، تجاوز Dio حزمة http من فريق Dart من حيث الشعبية، محتلاً المركز الأول بين عملاء HTTP في نظام Flutter البيئي وفقًا لـ pub.dev.

يدعم Dio ثلاثة محولات: DartNativeAdapter (افتراضيًا على Android و iOS و Desktop) و BrowserAdapter (على Web) و IOAdapter. يتم اختيار المحول تلقائيًا حسب المنصة. يوفر Dio أيضًا واجهة موحدة لجميع منصات Flutter — Android و iOS و Web و macOS و Windows و Linux.

كيف يعمل Dio

تعتمد بنية Dio على سلسلة معالجات. يمر كل طلب عبر سلسلة من المعترضات التي يمكنها تعديل الطلب (InterceptorsWrapper.onRequest) أو الاستجابة (onResponse) أو معالجة خطأ (onError). بعد المعترضات، يصل الطلب إلى المحولات (Transformer) التي تحول البيانات قبل الإرسال.

يتم تكوين مثيل Dio من خلال كائن BaseOptions يحتوي على عنوان URL الأساسي والرؤوس الافتراضية والمهلات ونوع الاستجابة (JSON أو stream أو plain) ومعاملات الاستعلام وتنسيق البيانات. تنطبق هذه الإعدادات على جميع الطلبات ولكن يمكن تجاوزها في طلب معين. يوفر BaseOptions نقطة تكوين واحدة للتطبيق بأكمله، مما يبسط تغييرات نقطة النهاية أو إضافة رؤوس عامة.

كل طلب في Dio يعيد Response<T>، حيث T هو نوع البيانات بعد معالجة المحول. افتراضيًا، يقوم Dio تلقائيًا بتحويل استجابات JSON إلى Map<String, dynamic>. للاستجابات المنمطة، يُستخدم Dio مع حزم التسلسل: json_serializable أو freezed أو built_value. تحتوي Response على data و headers و statusCode و requestOptions وبيانات إضافية.

التكوين العام لـ Dio

يتم إنشاء التكوين الأساسي عبر Dio(BaseOptions). يمكن تعيين baseUrl لجميع الطلبات و connectTimeout و receiveTimeout ورؤوس content-type و accept بالإضافة إلى queryParameters. تنطبق كل هذه المعاملات على كل طلب، مما يلغي تكرار الكود ويتمركز إدارة إعدادات الشبكة.

يدعم Dio وضعي تسلسل: JSON افتراضيًا (responseType: ResponseType.json) وتدفقي (ResponseType.stream). في وضع التدفق، يعيد Response.data ResponseBody يمكن قراءته بأجزاء. هذا مناسب لملفات الحمولة الكبيرة حيث لا يكون تحميل كل شيء في الذاكرة مرغوبًا. الوضع plain يعيد سلسلة نصية خام دون تحليل JSON تلقائي.

معترضات Dio

المعترضات هي الآلية الرئيسية لـ Dio لاعتراض وتعديل الطلبات والاستجابات والأخطاء. تحل محل Interceptor من OkHttp وإضافات Ktor تمامًا، ولكن مع API خاص بـ Dart ودعم غير متزامن عبر Future. يمكن إضافة المعترضات في التكوين العام لـ Dio أو للطلبات الفردية.

طريقة المعترضالغرضمثال استخدام
onRequestتعديل الطلب قبل الإرسالإضافة رمز التفويض
onResponseمعالجة الاستجابة الناجحةتحويل البيانات إلى كائنات DTO
onErrorمعالجة خطأ الطلبإعادة محاولة تلقائية عند 503

LogInterceptor

LogInterceptor المدمج يسجل كل طلب: الطريقة وعنوان URL والرؤوس والجسم ووقت التنفيذ. له وضعان: مضغوط (سطر واحد لكل طلب) وكامل (معلومات كاملة مع الجسم). LogInterceptor مفيد بشكل خاص أثناء التطوير، لكن يُنصح بتعطيله في إصدارات الإصدار باستخدام imports شرطية أو علامة عامة.

يتم إنشاء المعترضات المخصصة عبر فئة InterceptorsWrapper. يمكن تجاوز طريقة واحدة أو اثنتين أو الثلاثة (onRequest و onResponse و onError). ينفذ Dio المعترضات بدقة حسب ترتيب إضافتها إلى قائمة المعترضات. إذا لم يستدع المعترض handler.next()، تنقطع السلسلة ولا تصل الاستجابة أو الخطأ إلى التطبيق.

للمصادقة في Dio، يُستخدم معترض يضيف رمز Bearer إلى رأس Authorization. إذا أعاد الخادم 401، يحاول المعترض في onError تحديث الرمز عبر طلب تحديث ويعيد الطلب الأصلي بالرمز الجديد. هذا النمط يسمى token refresh interceptor ويتم تنفيذه عبر DioException بالتحقق من response?.statusCode == 401.

يوفر Dio دعمًا مدمجًا لإعادة المحاولة عبر حزمة dio_smart_retry أو RetryInterceptor مخصص. إعادة المحاولة مهمة لتطبيقات الجوال: عند فقدان الاتصال لمدة 2-3 ثوانٍ، يطرح Dio DioException من نوع connectionTimeout أو connectionError. يلتقط RetryInterceptor هذا الاستثناء ويعيد الطلب حتى 3 مرات مع تأخير أسي (1ث و 2ث و 4ث)، مما يحسن موثوقية التطبيق في ظروف الشبكة غير المستقرة.

أمثلة كود Dio في Dart

لنلق نظرة على طلب GET أساسي عبر Dio. يتم إنشاء مثيل مع BaseOptions، مع تعيين عنوان URL الأساسي والمهلات. يتم تنفيذ الطلب عبر طريقة get()، التي تعيد Response مع بيانات بتنسيق Map.

dart
final dio = Dio(BaseOptions(
    baseUrl: 'https://api.github.com',
    connectTimeout: Duration(seconds: 15),
    receiveTimeout: Duration(seconds: 15),
    headers: {
        'Accept': 'application/vnd.github.v3+json',
    },
))

final response = await dio.get('/users/octocat')
print(response.data['تسجيل الدخول'])

لـ طلب POST مع جسم JSON، يتم تمرير كائن Map أو DTO مخصص. يقوم Dio تلقائيًا بتسلسل Map إلى JSON عبر jsonEncode. لـ DTOs المنمطة، يُستخدم خيار queryParameters أو حقل data أو Transformer مخصص.

dart
final data = {
    'name': 'my-project',
    'description': 'Created via Dio',
    'private': false,
}

final response = await dio.post(
    '/user/repos',
    data: data,
    options: Options(
        contentType: ContentType.json.value,
    ),
)

print(response.data['المعرف'])

إضافة معترض تفويض

معترض مخصص يضيف رمز Bearer إلى كل طلب. يتم تشغيل طريقة onRequest قبل الإرسال، معدلة الرؤوس. عند استجابة 401، يمكن للمعترض تحديث الرمز وإعادة الطلب عبر طريقة dio.fetch(requestOptions).

dart
class AuthInterceptor extends InterceptorsWrapper {
    final String token

    AuthInterceptor(this.token)

    @override
    void onRequest(
        RequestOptions options,
        RequestInterceptorHandler handler,
    ) {
        options.headers['Authorization'] = 'Bearer $token'
        handler.next(options)
    }
}

dio.interceptors.add(AuthInterceptor('ghp_abc123'))

تحميل وتنزيل الملفات عبر Dio

يبسط Dio تحميل الملفات عبر FormData. لإرسال ملف، يتم إنشاء MultipartFile من File أو Bytes أو AssetBundle. يقوم FormData تلقائيًا بتعيين رأس multipart/form-data مع الحدود والتشفير الصحيحين. يدعم Dio تقدم التحميل عبر onSendProgress.

لتنزيل الملفات، تُستخدم طريقة download()، التي تحفظ تدفق البيانات مباشرة في ملف. يدعم Dio استئناف التنزيلات المتقطعة عبر رأس Range، وهو مفيد بشكل خاص للملفات الكبيرة. يتم تتبع تقدم التنزيل عبر onReceiveProgress، مما يسمح بعرض شريط تقدم في واجهة المستخدم.

dart
final formData = FormData.fromMap({
    'file': await MultipartFile.fromFile(
        '/path/to/photo.jpg',
        filename: 'photo.jpg',
    ),
    'description': 'Profile photo',
})

await dio.post(
    '/upload',
    data: formData,
    onSendProgress: (sent, total) {
        final progress = sent / total * 100
        print('رفع: $progress%')
    },
)

// تنزيل الملف
await dio.download(
    'https://example.com/file.zip',
    '/storage/emulated/0/Download/file.zip',
    onReceiveProgress: (received, total) {
        print('تنزيل: ${received / total * 100}%')
    },
)

الأخطاء الشائعة عند العمل مع Dio

معالجة الأخطاء غير الصحيحة هي المشكلة الأكثر شيوعًا. يطرح Dio DioException (المعروفة سابقًا بـ DioError) لأي مشاكل: انقطاع الشبكة أو المهلة أو أخطاء HTTP 4xx/5xx. يلتقط العديد من المطورين Exception العامة فقط، مما يفقد معلومات عن نوع الخطأ وإمكانية معالجته بشكل خاص. استخدم DioException.type لتحديد سبب الفشل.

تجاهل CancelToken يؤدي إلى تسرب الطلبات. إذا غادر المستخدم شاشة أثناء استمرار تنفيذ طلب، يهدر Dio الموارد وقد يحاول تحديث State مدمر. أنشئ دائمًا CancelToken لكل طلب وألغه في dispose(). يولد CancelToken DioException من نوع cancel، والتي يجب معالجتها بشكل صحيح.

عدم وجود منطق إعادة محاولة للأعطال المؤقتة. على الأجهزة المحمولة، غالبًا ما تكون الشبكة غير متاحة لفترة قصيرة. نفذ معترضًا مع إعادة محاولة تلقائية للطلب عند المهلة أو استجابة 503/502. استخدم RetryInterceptor من حزمة dio_smart_retry أو اكتب معترضًا مخصصًا مع تأخير أسي بين المحاولات.

الأسئلة الشائعة

كيف يختلف Dio عن حزمة http في Dart؟

Dio يوفر معترضات وتكوين BaseOptions عام و FormData وتقدم التحميل و CancelToken. حزمة http من فريق Dart بسيطة دون معترضات أو تكوين عام. يُستخدم Dio في المشاريع الكبيرة، بينما يُستخدم http في البرامج النصية البسيطة.

كيف تتم تسلسل JSON في Dio؟

افتراضيًا، يحول Dio JSON إلى Map باستخدام jsonDecode. للتسلسل المنمط، استخدم حزم json_serializable أو freezed. أنشئ معترضًا مخصصًا يحول response.data إلى DTO عبر fromJson() في onResponse.

كيف يتم إلغاء طلب في Dio؟

أنشئ CancelToken وقم بتمريره في خيارات الطلب. استدعاء token.cancel() يقطع الطلب ويطرح DioException من نوع cancel. يدعم CancelToken إلغاء طلبات متعددة في وقت واحد، وهو مناسب لإلغاء جميع الطلبات عند مغادرة الشاشة.

هل يعمل Dio على جميع منصات Flutter؟

نعم، يعمل Dio على جميع منصات Flutter الست: Android و iOS و Web و macOS و Windows و Linux. كل منصة تستخدم عميل HTTP متكيف: DartNativeAdapter (المنصات الأصلية) و BrowserAdapter (Web). واجهة برمجة تطبيقات موحدة لجميع المنصات هي ميزة رئيسية لـ Dio في مشاريع Flutter.

كيف يتعامل Dio مع الكوكيز؟

لا يدير Dio الكوكيز تلقائيًا. لدعم الكوكيز، استخدم حزمة dio_cookie_manager مع cookie_jar. يعترض CookieManager رؤوس Set-Cookie و Cookie ويحفظ الكوكيز في PersistCookieJar لإرسالها تلقائيًا في الطلبات اللاحقة لنفس النطاق.

الخلاصة

  • Dio — عميل HTTP الأكثر شعبية في Flutter مع معترضات ومحولات
  • المعترضات onRequest و onResponse و onError تعدل الطلبات والاستجابات
  • FormData و MultipartFile يبسطان تحميل الملفات إلى الخادم
  • CancelToken يلغي الطلبات بشكل صحيح لمنع تسرب الذاكرة
  • BaseOptions يمركز تكوين URL والرؤوس والمهلات
  • DioException يحتوي على نوع الخطأ لمعالجة مفصلة للأعطال
  • التقدم onSendProgress و onReceiveProgress يعرضان حالة التحميل

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا