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 team, заняв первое место среди HTTP-клиентов в Flutter-экосистеме по данным pub.dev.
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), query-параметры и формат данных. Эти настройки применяются ко всем запросам, но могут быть переопределены в конкретном запросе. BaseOptions обеспечивает единую точку конфигурации для всего приложения, что упрощает смену API-эндпоинта или добавление глобальных заголовков.
Каждый запрос в Dio возвращает Response<T>, где T — тип данных после обработки трансформерами. По умолчанию Dio автоматически преобразует JSON-ответ в Map<String, dynamic>. Для типизированных ответов используется Dio вместе с пакетами сериализации: json_serializable, freezed или built_value. Response содержит data, headers, statusCode, requestOptions и extra-данные.
Базовая конфигурация создаётся через Dio(BaseOptions). Можно задать baseUrl для всех запросов, connectTimeout и receiveTimeout, заголовки content-type и accept, а также queryParameters. Все эти параметры применяются к каждому запросу, что устраняет дублирование кода и централизует управление сетевыми настройками.
Dio поддерживает два режима сериализации: по умолчанию JSON (responseType: ResponseType.json) и потоковый (ResponseType.stream). В режиме stream Response.data возвращает ResponseBody, который можно читать частями. Это удобно для больших payload-файлов, когда полная загрузка в память нежелательна. Режим plain возвращает сырую строку без автоматического парсинга JSON.
Интерцепторы — ключевой механизм Dio для перехвата и модификации запросов, ответов и ошибок. Они полностью заменяют Interceptor из OkHttp и плагины из Ktor, но с Dart-специфичным API и поддержкой асинхронности через Future. Интерцепторы можно добавлять как в глобальной конфигурации Dio, так и для отдельных запросов.
| Метод интерцептора | Назначение | Пример использования |
|---|---|---|
| onRequest | Модификация запроса перед отправкой | Добавление токена авторизации |
| onResponse | Обработка успешного ответа | Преобразование data в DTO-объекты |
| onError | Обработка ошибки запроса | Автоматический retry при 503 |
Встроенный LogInterceptor логирует каждый запрос: метод, URL, заголовки, тело и время выполнения. Он имеет два режима: compact (одна строка на запрос) и full (полная информация с телом). LogInterceptor особенно полезен при разработке, но его рекомендуется отключать в релизных сборках через условный import или глобальный флаг.
Кастомные интерцепторы создаются через класс InterceptorsWrapper. Можно переопределить один, два или все три метода (onRequest, onResponse, onError). Dio выполняет интерцепторы строго в порядке их добавления в список interceptors. Если интерцептор не вызывает handler.next(), цепочка прерывается, и ответ/ошибка не доходят до приложения.
Для аутентификации в Dio используется интерцептор, добавляющий Bearer-токен в заголовок Authorization. Если сервер возвращает 401, интерцептор в onError пытается обновить токен через refresh-запрос и повторяет оригинальный запрос с новым токеном. Этот pattern называется token refresh interceptor и реализуется через DioException с проверкой response?.statusCode == 401.
Dio предоставляет встроенную поддержку retry-логики через пакет dio_smart_retry или кастомный RetryInterceptor. Ретрай важен для мобильных приложений: при потере соединения на 2–3 секунды Dio выбрасывает DioException с типом connectionTimeout или connectionError. RetryInterceptor перехватывает это исключение и повторяет запрос до 3 раз с экспоненциальной задержкой (1с, 2с, 4с), что повышает надёжность приложения в условиях нестабильной сети.
Рассмотрим базовый 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['login'])
Для POST-запроса с JSON-телом передаётся объект Map или кастомный DTO. Dio автоматически сериализует Map в JSON через jsonEncode. Для типизированных 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 срабатывает до отправки, модифицируя headers. При ответе 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('Upload: $progress%')
},
)
// Скачивание файла
await dio.download(
'https://example.com/file.zip',
'/storage/emulated/0/Download/file.zip',
onReceiveProgress: (received, total) {
print('Download: ${received / total * 100}%')
},
)
Неправильная обработка ошибок — самая частая проблема. Dio выбрасывает DioException (ранее DioError) при любых проблемах: отсутствие сети, таймаут, HTTP-ошибки 4xx/5xx. Многие разработчики ловят только generic Exception, теряя информацию о типе ошибки и возможности её кастомной обработки. Используйте DioException.type для определения причины сбоя.
Игнорирование CancelToken приводит к утечке запросов. Если пользователь ушёл с экрана, а запрос продолжает выполняться, Dio тратит ресурсы и может попытаться обновить уничтоженный State. Всегда создавайте CancelToken для каждого запроса и отменяйте его в dispose(). CancelToken генерирует DioException с типом cancel, который нужно правильно обрабатывать.
Отсутствие ретрай-логики для временных сбоев. На мобильных устройствах сеть часто недоступна кратковременно. Реализуйте интерцептор с автоматическим повторением запроса при таймауте или ответе 503/502. Используйте RetryInterceptor из пакета dio_smart_retry или напишите кастомный интерцептор с экспоненциальной задержкой между попытками.
Часто задаваемые вопросы
Dio предоставляет интерцепторы, глобальную конфигурацию BaseOptions, FormData, прогресс загрузки и CancelToken. Http-пакет от Dart team — минималистичный, без перехватчиков и глобальной конфигурации. Dio используют в крупных проектах, http — для простых скриптов.
Dio по умолчанию преобразует JSON в Map через jsonDecode. Для типизированной сериализации используйте пакеты json_serializable или freezed. Создайте кастомный интерцептор, который в onResponse преобразует response.data в DTO через fromJson().
Создайте CancelToken и передайте его в опции запроса. Вызов token.cancel() прерывает запрос и вызывает DioException с типом cancel. CancelToken поддерживает отмену нескольких запросов одновременно, что удобно для отмены всех запросов при выходе с экрана.
Да, Dio работает на всех шести платформах Flutter: Android, iOS, Web, macOS, Windows и Linux. Для каждой платформы используется адаптивный HTTP-клиент: DartNativeAdapter (нативные платформы) и BrowserAdapter (Web). Единый API для всех платформ — ключевое преимущество Dio в Flutter-проектах.
Dio не управляет cookie автоматически. Для поддержки cookie используется пакет dio_cookie_manager совместно с cookie_jar. CookieManager перехватывает Set-Cookie и Cookie заголовки и сохраняет куки в PersistCookieJar для автоматической отправки в следующих запросах к тому же домену.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также