Dio: что это, особенности HTTP-клиента для Flutter

Автор: IT Sectr Опубликовано: 2026-03-07 Время чтения: 8 мин

Dio — это мощный HTTP-клиент для Dart и Flutter, разработанный китайским инженером Вендой Вангом. Библиотека предоставляет продвинутый 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-сообществе.

Библиотека была создана Вендой Вангом в 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

Архитектура 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

Базовая конфигурация создаётся через Dio(BaseOptions). Можно задать baseUrl для всех запросов, connectTimeout и receiveTimeout, заголовки content-type и accept, а также queryParameters. Все эти параметры применяются к каждому запросу, что устраняет дублирование кода и централизует управление сетевыми настройками.

Dio поддерживает два режима сериализации: по умолчанию JSON (responseType: ResponseType.json) и потоковый (ResponseType.stream). В режиме stream Response.data возвращает ResponseBody, который можно читать частями. Это удобно для больших payload-файлов, когда полная загрузка в память нежелательна. Режим plain возвращает сырую строку без автоматического парсинга JSON.

Интерцепторы Dio

Интерцепторы — ключевой механизм Dio для перехвата и модификации запросов, ответов и ошибок. Они полностью заменяют Interceptor из OkHttp и плагины из Ktor, но с Dart-специфичным API и поддержкой асинхронности через Future. Интерцепторы можно добавлять как в глобальной конфигурации Dio, так и для отдельных запросов.

Метод интерцептораНазначениеПример использования
onRequestМодификация запроса перед отправкойДобавление токена авторизации
onResponseОбработка успешного ответаПреобразование data в DTO-объекты
onErrorОбработка ошибки запросаАвтоматический retry при 503

LogInterceptor

Встроенный 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с), что повышает надёжность приложения в условиях нестабильной сети.

Примеры кода 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['login'])

Для POST-запроса с JSON-телом передаётся объект Map или кастомный DTO. Dio автоматически сериализует Map в JSON через jsonEncode. Для типизированных DTO используется опция 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['id'])

Добавление интерцептора авторизации

Кастомный интерцептор добавляет Bearer-токен к каждому запросу. Метод onRequest срабатывает до отправки, модифицируя headers. При ответе 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 поддерживает докачку (resume) при прерванных загрузках через заголовок Range, что особенно полезно для больших файлов. Прогресс скачивания отслеживается через onReceiveProgress, позволяя отображать полосу загрузки в UI.

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('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

Неправильная обработка ошибок — самая частая проблема. 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 отличается от http-пакета Dart?

Dio предоставляет интерцепторы, глобальную конфигурацию BaseOptions, FormData, прогресс загрузки и CancelToken. Http-пакет от Dart team — минималистичный, без перехватчиков и глобальной конфигурации. Dio используют в крупных проектах, http — для простых скриптов.

Как сериализовать JSON в Dio?

Dio по умолчанию преобразует JSON в Map через jsonDecode. Для типизированной сериализации используйте пакеты json_serializable или freezed. Создайте кастомный интерцептор, который в onResponse преобразует response.data в DTO через fromJson().

Как отменить запрос в Dio?

Создайте CancelToken и передайте его в опции запроса. Вызов token.cancel() прерывает запрос и вызывает DioException с типом cancel. CancelToken поддерживает отмену нескольких запросов одновременно, что удобно для отмены всех запросов при выходе с экрана.

Работает ли Dio на всех платформах Flutter?

Да, Dio работает на всех шести платформах Flutter: Android, iOS, Web, macOS, Windows и Linux. Для каждой платформы используется адаптивный HTTP-клиент: DartNativeAdapter (нативные платформы) и BrowserAdapter (Web). Единый API для всех платформ — ключевое преимущество Dio в Flutter-проектах.

Как Dio обрабатывает cookie?

Dio не управляет cookie автоматически. Для поддержки cookie используется пакет 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также