Dio es un potente cliente HTTP para Dart y Flutter, creado por el ingeniero chino Wenda Wang. La biblioteca ofrece una API avanzada con soporte para interceptores, FormData, carga de archivos y cancelación de solicitudes. Según pub.dev, 2025, Dio es el cliente HTTP más popular en el ecosistema Flutter con más de 8 mil estrellas en GitHub.
Puntos clave
Dio es una potente biblioteca cliente HTTP para el lenguaje Dart, más ampliamente utilizada en aplicaciones Flutter. Dio proporciona una API rica con soporte para interceptores, configuración global, transformadores, FormData, carga de archivos y gestión flexible de tiempos de espera, convirtiéndolo en la opción principal para la comunicación en red en la comunidad Flutter.
La biblioteca fue creada por Wenda Wang en 2018 como alternativa al HttpClient integrado de dart:io, que carecía de muchas funciones modernas: configuración unificada para todas las solicitudes, interceptores y serialización automática. Para 2025, Dio superó en popularidad al paquete http del equipo de Dart, ocupando el primer lugar entre los clientes HTTP en el ecosistema Flutter según pub.dev.
Dio soporta tres adaptadores: DartNativeAdapter (predeterminado en Android, iOS, Escritorio), BrowserAdapter (en Web) e IOAdapter. El adaptador se selecciona automáticamente según la plataforma. Dio también proporciona una interfaz unificada para todas las plataformas Flutter: Android, iOS, Web, macOS, Windows y Linux.
La arquitectura de Dio se basa en una cadena de manejadores. Cada solicitud pasa por una secuencia de interceptores que pueden modificar la solicitud (InterceptorsWrapper.onRequest), la respuesta (onResponse) o manejar un error (onError). Después de los interceptores, la solicitud llega a los transformadores (Transformer), que transforman los datos antes de enviarlos.
Una instancia de Dio se configura a través de un objeto BaseOptions que contiene la URL base, encabezados predeterminados, tiempos de espera, tipo de respuesta (JSON, stream, plain), parámetros de consulta y formato de datos. Esta configuración se aplica a todas las solicitudes, pero puede anularse en una solicitud específica. BaseOptions proporciona un punto de configuración único para toda la aplicación, simplificando los cambios de endpoint o la adición de encabezados globales.
Cada solicitud de Dio devuelve Response<T>, donde T es el tipo de datos después del procesamiento del transformador. Por defecto, Dio convierte automáticamente las respuestas JSON a Map<String, dynamic>. Para respuestas tipadas, Dio se usa junto con paquetes de serialización: json_serializable, freezed o built_value. Response contiene data, headers, statusCode, requestOptions y datos extra.
La configuración básica se crea mediante Dio(BaseOptions). Se puede establecer un baseUrl para todas las solicitudes, connectTimeout y receiveTimeout, encabezados content-type y accept, así como queryParameters. Todos estos parámetros se aplican a cada solicitud, eliminando la duplicación de código y centralizando la gestión de la configuración de red.
Dio soporta dos modos de serialización: JSON por defecto (responseType: ResponseType.json) y streaming (ResponseType.stream). En modo stream, Response.data devuelve un ResponseBody que se puede leer en fragmentos. Esto es conveniente para archivos grandes donde no es deseable cargar todo en memoria. El modo plain devuelve una cadena sin procesar sin análisis JSON automático.
Los interceptores son el mecanismo clave de Dio para interceptar y modificar solicitudes, respuestas y errores. Reemplazan completamente el Interceptor de OkHttp y los plugins de Ktor, pero con una API específica de Dart y soporte asíncrono mediante Future. Los interceptores se pueden añadir tanto en la configuración global de Dio como para solicitudes individuales.
| Método del interceptor | Propósito | Ejemplo de uso |
|---|---|---|
| onRequest | Modificar la solicitud antes de enviar | Añadir token de autorización |
| onResponse | Manejar respuesta exitosa | Convertir datos a objetos DTO |
| onError | Manejar error de solicitud | Reintento automático en 503 |
El LogInterceptor integrado registra cada solicitud: método, URL, encabezados, cuerpo y tiempo de ejecución. Tiene dos modos: compacto (una línea por solicitud) y completo (información completa con cuerpo). LogInterceptor es especialmente útil durante el desarrollo, pero se recomienda desactivarlo en compilaciones de lanzamiento mediante importaciones condicionales o una bandera global.
Los interceptores personalizados se crean mediante la clase InterceptorsWrapper. Se pueden sobrescribir uno, dos o los tres métodos (onRequest, onResponse, onError). Dio ejecuta los interceptores estrictamente en el orden en que se añaden a la lista de interceptores. Si un interceptor no llama a handler.next(), la cadena se interrumpe y la respuesta o error no llega a la aplicación.
Para autenticación en Dio, se usa un interceptor que añade un token Bearer al encabezado Authorization. Si el servidor devuelve 401, el interceptor en onError intenta renovar el token mediante una solicitud de actualización y repite la solicitud original con el nuevo token. Este patrón se llama token refresh interceptor y se implementa mediante DioException verificando response?.statusCode == 401.
Dio proporciona soporte integrado para lógica de reintento mediante el paquete dio_smart_retry o un RetryInterceptor personalizado. El reintento es importante para aplicaciones móviles: cuando la conexión se pierde durante 2-3 segundos, Dio lanza una DioException con tipo connectionTimeout o connectionError. RetryInterceptor captura esta excepción y reintenta la solicitud hasta 3 veces con retroceso exponencial (1s, 2s, 4s), mejorando la fiabilidad de la aplicación en condiciones de red inestables.
Veamos una solicitud GET básica con Dio. Se crea una instancia con BaseOptions, estableciendo la URL base y los tiempos de espera. La solicitud se ejecuta mediante el método get(), que devuelve una Response con datos en formato 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['iniciar sesión'])
Para una solicitud POST con cuerpo JSON, se pasa un objeto Map o un DTO personalizado. Dio serializa automáticamente el Map a JSON mediante jsonEncode. Para DTOs tipados, se utiliza la opción queryParameters, el campo data o un Transformer personalizado.
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'])
Un interceptor personalizado añade un token Bearer a cada solicitud. El método onRequest se activa antes del envío, modificando los encabezados. Ante una respuesta 401, el interceptor puede renovar el token y reintentar la solicitud mediante el método 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 simplifica la carga de archivos mediante FormData. Para enviar un archivo, se crea un MultipartFile a partir de File, Bytes o AssetBundle. FormData establece automáticamente el encabezado multipart/form-data con el límite y la codificación correctos. Dio soporta el progreso de carga mediante onSendProgress.
Para la descarga de archivos, se utiliza el método download(), que guarda el flujo de datos directamente en un archivo. Dio soporta la reanudación de descargas interrumpidas mediante el encabezado Range, lo que es especialmente útil para archivos grandes. El progreso de descarga se rastrea mediante onReceiveProgress, permitiendo mostrar una barra de progreso en la interfaz de usuario.
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('Subida: $progress%')
},
)
// Descarga de archivos
await dio.download(
'https://example.com/file.zip',
'/storage/emulated/0/Download/file.zip',
onReceiveProgress: (received, total) {
print('Descarga: ${received / total * 100}%')
},
)
El manejo incorrecto de errores es el problema más frecuente. Dio lanza una DioException (anteriormente DioError) ante cualquier problema: falta de red, tiempo de espera, errores HTTP 4xx/5xx. Muchos desarrolladores solo capturan la Exception genérica, perdiendo información sobre el tipo de error y la capacidad de manejarlo específicamente. Use DioException.type para determinar la causa del fallo.
Ignorar CancelToken provoca fugas de solicitudes. Si un usuario sale de una pantalla mientras una solicitud aún se está ejecutando, Dio desperdicia recursos y puede intentar actualizar un State destruido. Cree siempre un CancelToken para cada solicitud y cancélelo en dispose(). CancelToken genera una DioException con tipo cancel, que debe manejarse correctamente.
Falta de lógica de reintento para fallos temporales. En dispositivos móviles, la red suele no estar disponible brevemente. Implemente un interceptor con reintento automático de solicitudes en caso de tiempo de espera o respuesta 503/502. Use RetryInterceptor del paquete dio_smart_retry o escriba un interceptor personalizado con retroceso exponencial entre intentos.
Preguntas frecuentes
Dio proporciona interceptores, configuración global BaseOptions, FormData, progreso de carga y CancelToken. El paquete http del equipo de Dart es minimalista, sin interceptores ni configuración global. Dio se usa en proyectos grandes, mientras que http se usa para scripts simples.
Por defecto, Dio convierte JSON a Map usando jsonDecode. Para serialización tipada, use los paquetes json_serializable o freezed. Cree un interceptor personalizado que convierta response.data a DTO mediante fromJson() en onResponse.
Cree un CancelToken y pase las opciones de la solicitud. Llamar a token.cancel() interrumpe la solicitud y lanza una DioException con tipo cancel. CancelToken soporta la cancelación de múltiples solicitudes simultáneamente, lo cual es conveniente para cancelar todas las solicitudes al salir de una pantalla.
Sí, Dio funciona en las seis plataformas Flutter: Android, iOS, Web, macOS, Windows y Linux. Cada plataforma utiliza un cliente HTTP adaptativo: DartNativeAdapter (plataformas nativas) y BrowserAdapter (Web). Una API unificada para todas las plataformas es una ventaja clave de Dio en proyectos Flutter.
Dio no gestiona las cookies automáticamente. Para soporte de cookies, use el paquete dio_cookie_manager junto con cookie_jar. CookieManager intercepta los encabezados Set-Cookie y Cookie y guarda las cookies en PersistCookieJar para enviarlas automáticamente en solicitudes posteriores al mismo dominio.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también