Dio — یک کلاینت HTTP قدرتمند برای Dart و Flutter است که توسط مهندس چینی وندا وانگ ساخته شده است. این کتابخانه API پیشرفتهای با پشتیبانی از رهگیرها، FormData، آپلود فایلها و لغو درخواستها ارائه میدهد. بر اساس دادههای pub.dev, 2025، Dio محبوبترین کلاینت HTTP در اکوسیستم Flutter با بیش از 8 هزار ستاره در GitHub است.
نکات کلیدی
Dio — یک کتابخانه قدرتمند کلاینت HTTP برای زبان Dart است که بیشترین استفاده را در برنامههای Flutter دارد. Dio API غنی با پشتیبانی از رهگیرها، پیکربندی سراسری، تبدیلکنندهها، FormData، آپلود فایلها و مدیریت انعطافپذیر مهلت زمانی ارائه میدهد که آن را به انتخاب اصلی برای ارتباطات شبکهای در جامعه Flutter تبدیل میکند.
این کتابخانه توسط وندا وانگ در سال 2018 به عنوان جایگزینی برای dart:io HttpClient داخلی ساخته شد که بسیاری از قابلیتهای مدرن را نداشت: پیکربندی یکپارچه برای همه درخواستها، رهگیرها و سریالسازی خودکار. تا سال 2025، Dio از بسته http تیم Dart از نظر محبوبیت پیشی گرفت و طبق دادههای pub.dev رتبه اول را در میان کلاینتهای HTTP در اکوسیستم Flutter به دست آورد.
Dio از سه آداپتور پشتیبانی میکند: DartNativeAdapter (پیشفرض در Android، iOS، Desktop)، BrowserAdapter (در Web) و IOAdapter. آداپتور به طور خودکار بر اساس پلتفرم انتخاب میشود. Dio همچنین یک رابط یکپارچه برای همه پلتفرمهای Flutter — Android، iOS، Web، macOS، Windows و Linux — فراهم میکند.
معماری Dio بر اساس زنجیره پردازشگرها (handler chain) ساخته شده است. هر درخواست از دنبالهای از رهگیرها عبور میکند که میتوانند درخواست (InterceptorsWrapper.onRequest)، پاسخ (onResponse) را تغییر دهند یا خطا (onError) را مدیریت کنند. پس از رهگیرها، درخواست به تبدیلکنندهها (Transformer) میرسد که دادهها را قبل از ارسال تبدیل میکنند.
نمونه Dio از طریق شی BaseOptions پیکربندی میشود که شامل URL پایه، هدرهای پیشفرض، مهلتهای زمانی، نوع پاسخ (JSON، stream، plain)، پارامترهای جستجو و فرمت داده است. این تنظیمات برای همه درخواستها اعمال میشوند، اما میتوانند در یک درخواست خاص بازنویسی شوند. BaseOptions یک نقطه پیکربندی یکپارچه برای کل برنامه فراهم میکند که تغییر endpoint API یا افزودن هدرهای سراسری را ساده میکند.
هر درخواست در Dio Response<T> را برمیگرداند، جایی که T — نوع دادهها پس از پردازش توسط تبدیلکنندهها است. به طور پیشفرض Dio به طور خودکار پاسخ JSON را به Map<String, dynamic> تبدیل میکند. برای پاسخهای تایپشده از Dio همراه با بستههای سریالسازی استفاده میشود: json_serializable، freezed یا built_value. Response شامل data، headers، statusCode، requestOptions و دادههای اضافی است.
پیکربندی پایه از طریق Dio(BaseOptions) ایجاد میشود. میتوان baseUrl برای همه درخواستها، connectTimeout و receiveTimeout، هدرهای content-type و accept و همچنین queryParameters را تنظیم کرد. همه این پارامترها برای هر درخواست اعمال میشوند که تکرار کد را حذف کرده و مدیریت تنظیمات شبکه را متمرکز میکند.
Dio از دو حالت سریالسازی پشتیبانی میکند: پیشفرض JSON (responseType: ResponseType.json) و جریانی (ResponseType.stream). در حالت جریانی، Response.data یک ResponseBody برمیگرداند که میتوان آن را بخشبخش خواند. این برای فایلهای payload بزرگ مناسب است، زمانی که بارگذاری کامل در حافظه مطلوب نیست. حالت plain یک رشته خام بدون تجزیه خودکار JSON برمیگرداند.
رهگیرها — مکانیزم کلیدی Dio برای رهگیری و تغییر درخواستها، پاسخها و خطاها هستند. آنها به طور کامل جایگزین Interceptor از OkHttp و پلاگینهای Ktor میشوند، اما با API مخصوص Dart و پشتیبانی از ناهمزمانی از طریق Future. رهگیرها را میتوان هم در پیکربندی سراسری Dio و هم برای درخواستهای جداگانه اضافه کرد.
| روش رهگیر | هدف | مثال استفاده |
|---|---|---|
| onRequest | تغییر درخواست قبل از ارسال | افزودن توکن احراز هویت |
| onResponse | پردازش پاسخ موفق | تبدیل داده به اشیاء DTO |
| onError | پردازش خطای درخواست | تلاش مجدد خودکار در 503 |
LogInterceptor داخلی هر درخواست را ثبت میکند: روش، URL، هدرها، بدنه و زمان اجرا. این دو حالت دارد: فشرده (یک خط به ازای هر درخواست) و کامل (اطلاعات کامل با بدنه). LogInterceptor به ویژه در طول توسعه مفید است، اما توصیه میشود در نسخههای release آن را از طریق import شرطی یا پرچم سراسری غیرفعال کنید.
رهگیرهای سفارشی از طریق کلاس InterceptorsWrapper ایجاد میشوند. میتوان یک، دو یا هر سه روش (onRequest، onResponse، onError) را بازنویسی کرد. Dio رهگیرها را به ترتیب دقیق اضافه شدن آنها در لیست interceptors اجرا میکند. اگر رهگیر handler.next() را فراخوانی نکند، زنجیره قطع میشود و پاسخ/خطا به برنامه نمیرسد.
برای احراز هویت در Dio از رهگیری استفاده میشود که توکن Bearer را به هدر Authorization اضافه میکند. اگر سرور 401 برگرداند، رهگیر در onError سعی میکند توکن را از طریق درخواست refresh بهروز کند و درخواست اصلی را با توکن جدید تکرار میکند. این الگو token refresh interceptor نامیده میشود و از طریق DioException با بررسی response?.statusCode == 401 پیادهسازی میشود.
Dio پشتیبانی داخلی از منطق تلاش مجدد را از طریق بسته dio_smart_retry یا RetryInterceptor سفارشی فراهم میکند. تلاش مجدد برای برنامههای موبایل مهم است: هنگام قطع اتصال به مدت 2–3 ثانیه، Dio DioException را با نوع connectionTimeout یا connectionError پرتاب میکند. RetryInterceptor این استثنا را گرفته و درخواست را تا 3 بار با تأخیر نمایی (1s، 2s، 4s) تکرار میکند که قابلیت اطمینان برنامه را در شرایط شبکه ناپایدار افزایش میدهد.
درخواست GET پایه از طریق Dio را بررسی میکنیم. یک نمونه با BaseOptions ایجاد میشود، URL پایه و مهلتهای زمانی تنظیم میشود. درخواست از طریق متد get() اجرا میشود و Response را با دادهها در قالب Map برمیگرداند.
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 را از طریق jsonEncode به JSON سریالسازی میکند. برای DTO تایپشده از گزینه queryParameters، فیلد data یا Transformer سفارشی استفاده میشود.
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['id'])
رهگیر سفارشی توکن Bearer را به هر درخواست اضافه میکند. متد onRequest قبل از ارسال فعال میشود و هدرها را تغییر میدهد. در پاسخ 401، رهگیر میتواند توکن را بهروز کرده و درخواست را از طریق متد dio.fetch(requestOptions) تکرار کند.
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 آپلود فایلها را از طریق FormData ساده میکند. برای ارسال فایل، MultipartFile از File، Bytes یا AssetBundle ایجاد میشود. FormData به طور خودکار هدر multipart/form-data را با مرز و رمزگذاری صحیح تنظیم میکند. Dio پیشرفت آپلود را از طریق onSendProgress پشتیبانی میکند.
برای دانلود فایلها از متد download() استفاده میشود که جریان داده را مستقیماً در فایل ذخیره میکند. Dio ادامه دانلود (resume) را برای دانلودهای قطع شده از طریق هدر Range پشتیبانی میکند که به ویژه برای فایلهای بزرگ مفید است. پیشرفت دانلود از طریق onReceiveProgress ردیابی میشود و امکان نمایش نوار پیشرفت در UI را فراهم میکند.
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 در هر مشکلی DioException (قبلاً DioError) پرتاب میکند: عدم وجود شبکه، مهلت زمانی، خطاهای HTTP 4xx/5xx. بسیاری از توسعهدهندگان فقط Exception عمومی را میگیرند و اطلاعات مربوط به نوع خطا و امکان مدیریت سفارشی آن را از دست میدهند. از DioException.type برای تعیین علت خرابی استفاده کنید.
نادیده گرفتن CancelToken منجر به نشت درخواست میشود. اگر کاربر صفحه را ترک کند اما درخواست همچنان در حال اجرا باشد، Dio منابع را مصرف میکند و ممکن است سعی کند State نابود شده را بهروز کند. همیشه برای هر درخواست CancelToken ایجاد کنید و آن را در dispose() لغو کنید. CancelToken DioException با نوع cancel ایجاد میکند که باید به درستی مدیریت شود.
عدم وجود منطق تلاش مجدد برای خرابیهای موقت. در دستگاههای موبایل، شبکه اغلب به طور موقت در دسترس نیست. یک رهگیر با تکرار خودکار درخواست در مهلت زمانی یا پاسخ 503/502 پیادهسازی کنید. از RetryInterceptor از بسته dio_smart_retry استفاده کنید یا یک رهگیر سفارشی با تأخیر نمایی بین تلاشها بنویسید.
سوالات متداول
Dio رهگیرها، پیکربندی سراسری BaseOptions، FormData، پیشرفت آپلود و CancelToken را ارائه میدهد. بسته http تیم Dart — مینیمال، بدون رهگیر و پیکربندی سراسری. Dio در پروژههای بزرگ استفاده میشود، http — برای اسکریپتهای ساده.
Dio به طور پیشفرض JSON را از طریق jsonDecode به Map تبدیل میکند. برای سریالسازی تایپشده از بستههای json_serializable یا freezed استفاده کنید. یک رهگیر سفارشی ایجاد کنید که در onResponse داده response.data را از طریق fromJson() به DTO تبدیل کند.
CancelToken ایجاد کنید و آن را به گزینههای درخواست ارسال کنید. فراخوانی token.cancel() درخواست را قطع کرده و DioException با نوع cancel ایجاد میکند. CancelToken از لغو چندین درخواست به طور همزمان پشتیبانی میکند که برای لغو همه درخواستها هنگام خروج از صفحه مفید است.
بله، Dio در هر شش پلتفرم Flutter کار میکند: Android، iOS، Web، macOS، Windows و Linux. برای هر پلتفرم از یک کلاینت HTTP تطبیقی استفاده میشود: DartNativeAdapter (پلتفرمهای بومی) و BrowserAdapter (Web). API یکپارچه برای همه پلتفرمها — مزیت کلیدی Dio در پروژههای Flutter است.
Dio کوکی را به طور خودکار مدیریت نمیکند. برای پشتیبانی از کوکی از بسته dio_cookie_manager به همراه cookie_jar استفاده میشود. CookieManager هدرهای Set-Cookie و Cookie را رهگیری کرده و کوکیها را در PersistCookieJar برای ارسال خودکار در درخواستهای بعدی به همان دامنه ذخیره میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید