Cuando tu aplicación consume datos de una API, la respuesta no siempre será exitosa. Los datos pueden tardar en llegar, la lista puede venir vacía o la llamada puede fallar por completo. Saber manejar estos tres escenarios es fundamental para ofrecer una experiencia de usuario sólida y profesional en Flutter.
¿Cómo validar el estado de carga en Flutter?
Antes de construir la vista con los datos, es necesario agregar validaciones sobre el estado de la conexión. El primer caso que se debe cubrir es cuando la información aún se está cargando [01:05].
Para esto se utiliza un condicional if que evalúa el snapshot proveniente de la llamada asíncrona. Se pregunta si el connectionState se encuentra en estado waiting, es decir, esperando respuesta. Si la condición se cumple, se retorna un widget centrado con un CircularProgressIndicator [01:25], que muestra un círculo de carga girando hasta que la información esté disponible.
dart
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
El CircularProgressIndicator es una widget de Flutter que indica visualmente al usuario que algo se está procesando. Es una práctica estándar en aplicaciones móviles para evitar pantallas en blanco durante la espera.
¿Qué hacer cuando la data llega vacía o nula?
El segundo escenario cubre los casos en que la respuesta llega, pero no contiene datos útiles [01:42]. Se implementa con un else if que realiza dos validaciones:
- Verificar si el
snapshot.data es null (dato nulo).
- Verificar si la lista está vacía usando la propiedad
isEmpty.
dart
else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(
child: Text('No recipes found'),
);
}
Si cualquiera de las dos condiciones se cumple, se retorna un texto centrado indicando que no hay recetas disponibles. Este manejo es importante porque evita errores en tiempo de ejecución cuando se intenta iterar sobre una lista vacía o nula.
Para probar este caso se puede utilizar Mockoon [02:33], una herramienta que simula respuestas de API. Basta con configurar la respuesta para que devuelva una lista vacía y recargar la aplicación. El resultado esperado es que aparezca el mensaje de "no recipes found" en pantalla.
¿Cómo se muestra la vista cuando todo es correcto?
El tercer y último bloque corresponde al caso exitoso. Se coloca un else que contiene el ListView con los datos renderizados [02:24]. Este fue el primer componente construido en clases anteriores, y ahora queda correctamente protegido por las validaciones previas.
¿Cómo manejar errores en la llamada a la API con try catch?
No basta con validar lo que el usuario ve en pantalla. También es necesario capturar errores desde la propia llamada HTTP [03:00]. Para esto se envuelve la lógica de la solicitud en un bloque try catch.
Dentro del try, se espera la respuesta de la URL y se evalúa el status code [03:18]. Si el código es 200, significa que la solicitud fue exitosa y se procede a guardar los datos para enviarlos al front.
dart
try {
final response = await http.get(url);
if (response.statusCode == 200) {
// Procesar y retornar datos
} else {
print('Error: ${response.statusCode}');
return [];
}
} catch (e) {
print('Error en la request: $e');
return [];
}
¿Qué sucede cuando el status code no es 200?
Si la respuesta no es exitosa, se imprime un mensaje en consola que incluye el status code mediante interpolación de variables con ${} [03:45]. Además, se retorna una lista vacía para que el front active la validación de datos vacíos y muestre el mensaje correspondiente.
¿Qué ocurre si la llamada falla por completo?
El bloque catch captura cualquier excepción que ocurra durante la solicitud, como problemas de red o errores inesperados [04:13]. Se imprime el error en consola y se retorna igualmente una lista vacía.
Con estas tres capas de protección —estado de carga, datos vacíos y errores en la solicitud— la aplicación queda preparada para cualquier escenario. Manejar correctamente estos casos mejora de forma significativa la experiencia de usuario y la estabilidad del proyecto.
¿Has implementado algún otro patrón para manejar errores en tus aplicaciones Flutter? Comparte tu experiencia en los comentarios.