FutureBuilder, async, await en Flutter, ejemplo practico
Índice de contenido
- Qué es FutureBuilder y para qué sirve
- Los futuros y la UI asíncrona
- Cómo funciona FutureBuilder (explicación clara y directa)
- El snapshot y sus estados
- Ejemplo real: FutureBuilder con una API
- El widget FutureBuilder
- Construyendo la UI en el builder
- Errores típicos que he visto (y cómo evitarlos)
- Buenas prácticas, usa el try catch JODERRRR!
- Cuándo NO usar FutureBuilder
- FAQs rápidas sobre FutureBuilder
- Conclusión
Hoy vamos a tratar un widget incomprendido como lo es el FutureBuilder; que a primera vista puede parecer abstracto y difícil de emplear, pero, tiene un uso muy particular que nos puede ayudar a completar con éxito un desarrollo que involucre un proceso asíncrono con el cual, a la final queramos dibujar un widget.
Seguramente si estas iniciando en Flutter el FutureBuilder te parece uno de esos widgets “misteriosos” y dificiles de usar que todos usan, pero que nadie termina de explicar bien. Y te soy honesto: la primera vez que lo vi, pensé exactamente lo que tú probablemente pensaste: “¿Y ahora qué hago con esto?”.
Esta guía te ayudará a entender como emplear el widget FutureBuilder de manera correcta; recordemos que quedamos en que conocemos como crear listados con el ListView en Flutter.
El FutureBuilder no es complicado: simplemente hay que dominar su lógica de ejecución y saber qué esperar del famoso snapshot.
Qué es FutureBuilder y para qué sirve
El FutureBuilder es un widget que te permite construir UI basada en el resultado de un Future, es decir, de un proceso asíncrono que terminará “más tarde”. En Flutter no puedes bloquear la UI mientras esperas datos, así que necesitas una forma elegante de:
- Mostrar algo mientras cargas.
- Mostrar el resultado cuando lo tengas.
- Manejar errores si algo falla.
Eso es exactamente lo que resuelve FutureBuilder.
Los futuros y la UI asíncrona
Un Future<T> es una promesa: “te devolveré un valor de tipo T… pero no ahora”, si vienes de JavaScript o Python, son los famosos async y await, cada vez que hacemos una petición HTTP, es un proceso asíncrono y en las apps móviles en el 99.9% de los casos, usamos un FutureBuilder para alguna operación con la red, es decir, con Internet.
Puede ser una llamada a una API, una operación de lectura, o cualquier trabajo que no sea inmediato.
Cuando construyes UI que depende de un future, necesitas reaccionar a sus estados. Aquí entra el FutureBuilder.
Cómo funciona FutureBuilder (explicación clara y directa)
Parámetros esenciales: future y builder
Estos son los dos parámetros que mandan:
- future: → la función asíncrona que vas a ejecutar
- builder: → un callback que se reconstruye automáticamente cuando el future termina
El snapshot y sus estados
El snapshot tiene información crítica:
- snapshot.hasData, si hay data.
- snapshot.hasError, si ocurrió un error.
- snapshot.connectionState, estado de la conexión.
- ConnectionState.waiting → esperando respuesta
- ConnectionState.done → future resuelto
- ConnectionState.active → muy poco usado con FutureBuilder
- ConnectionState.none → no se ejecutó ningún future
- snapshot.data, la data.
Y aquí un punto importante que aprendí en un proyecto real:
si tu future lanza una excepción, el FutureBuilder nunca llega al estado “done”, así que no confíes ciegamente en hasData.
Ejemplo real: FutureBuilder con una API
El widget FutureBuilder
De manera demostrativa el proceso asíncrono, o lo que es lo mismo, aquella función que retorna un Future, que en la práctica es una función que realiza al menos un proceso asíncrono, lo que hace es conectarse a Internet mediante una URL y obtener datos:
static Future<List<dynamic>> getComments(int classId) async {
var url = Uri.https(baseUrlAPI, "<URL>");
try {
final response = await http.get(url);
if (response.statusCode == 200) {
return jsonMap['comments']);
}
} on Exception {}
return [];
}Construyendo la UI en el builder
Ahora, el future es tan fácil de emplear como indicar en el parámetro future, el método asíncrono creado anteriormente, luego, en el parámetro de builder, que es un callback, es donde construimos el widget que necesita la data de entrada provista por el future; en nuestro ejemplo, es el listado de datos:
Widget _listComments() {
return FutureBuilder(
future: AcademyHelper.getComments(5),
builder: (_, snapshot) {
if (snapshot.hasData && snapshot.data != null) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data?.length, // comments
itemBuilder: (_, int position) =>
Text(snapshot.data?[position]['comment']));
} else {
return const CircularProgressIndicator();
}
},
);
}Como puedes ver, no tenemos devuelta la data de manera directa, si no, tenemos un objeto llamado snapshot, que no es más que un envoltorio para nuestros datos; la razón de esto se debe a que este objeto nos da el estado de la petición, ya que, al ser un proceso asíncrono, vamos a querer dibujar un widget ANTES de cargar los datos, que es luego reemplazado por el widget construido a partir de los datos.
El snapshot tiene parámetros como hasData que especifica si ya el future fué resuelto; es muy importante que desde el future NO ocurra una excepción ya que, el future nunca sería resuelto.
Errores típicos que he visto (y cómo evitarlos)
- El future lanza excepción y nunca se resuelve → captura siempre errores.
- Hacer la llamada dentro del builder → malísimo, provoca múltiples peticiones.
- Devolver null en lugar de listas vacías → genera errores silenciosos.
- Abusar del FutureBuilder en la misma pantalla → preferible combinarlo con controladores o Providers.
Buenas prácticas, usa el try catch JODERRRR!
El error más común es que el future nunca se resuelva, siempre hago:
try {} catch (_) {
return [];
}Cuándo NO usar FutureBuilder
- Cuando necesitas varias actualizaciones en tiempo real → usa StreamBuilder.
- Cuando la data se usa en múltiples widgets → usa un estado global (Provider, Riverpod, Bloc).
- Cuando la pantalla tiene múltiples secciones dependientes → crear un FutureBuilder por cada una puede ser innecesario.
FAQs rápidas sobre FutureBuilder
- ¿Cómo manejo errores dentro de FutureBuilder?
- Captura excepciones en el future y maneja hasError.
- ¿Por qué FutureBuilder no se vuelve a ejecutar?
- Porque un future sólo corre una vez. Usa un método que genere un nuevo future o encapsúlalo en un botón/acción.
- ¿Puedo usar varios FutureBuilders en una pantalla?
- Sí, pero no abuses. La pantalla puede volverse lenta.
- ¿Es malo anidar FutureBuilders?
- Casi siempre sí. Encadena futuros o usa estado global.
Conclusión
A la final el FutureBuilder es particularmente útil, cuando no podemos emplear un proceso asíncrono directamente en el árbol de widget, y no podemos hacer un setState para redibujar el widget, ya que, el FutureBuilder se reconstruye de manera automática al obtener los datos; es como si fuera un statefulwidget automatizado que se construye automáticamente al obtener los datos.
El FutureBuilder no es complicado: es predecible y muy útil cuando tienes un proceso asíncrono que termina una única vez.
Después de usarlo repetidamente para cargar datos desde APIs, entendí que su poder real está en que te libera del estado manual: él reconstruye la UI por ti cuando llegue la data.
Si aprendes a leer el snapshot, evitas ejecutar futuros múltiples veces y manejas errores con cuidado, se convierte en uno de los widgets más confiables del ecosistema Flutter.
El siguiente paso, consiste en aprender a usar las rutas y navegación en Flutter.
Acepto recibir anuncios de interes sobre este Blog.
Hoy vamos a tratar un widget incomprendido como lo es el FutureBuilder; que a primera vista puede parecer abstracto y difícil de emplear, pero, tiene un uso muy particular que nos puede ayudar a completar con éxito un desarrollo que involucre un proceso asíncrono con el cual, a la final queramos dibujar un widget.