El problema

La mayoría de las apps Flutter necesitan ejecutar tareas que tardan unos segundos: pedir datos a una API, subir un archivo o procesar un pago. Durante esa espera el usuario mira una pantalla congelada sin ninguna señal de que esté pasando algo. Vuelve a pulsar el botón, provoca peticiones duplicadas o da por hecho que la app se ha caído.

La solución habitual es gestionar a mano un estado de carga: cambiar un booleano, mostrar un spinner, esperar al future, ocultar el spinner y luego manejar el resultado o el error. Esa lógica acaba duplicada en decenas de pantallas con diferencias sutiles cada vez.

Los problemas más comunes son:

  • Código repetitivo de gestión del estado de carga repetido en cada pantalla
  • Usuarios pulsando botones varias veces porque no hay respuesta visual
  • Diálogos descartados que dejan futures huérfanos ejecutándose en segundo plano
  • Manejo de errores inconsistente: unas pantallas capturan excepciones y otras fallan en silencio

Cómo lo resuelve flutter_future_progress_dialog

flutter_future_progress_dialog sustituye todo ese código repetitivo por una única llamada a función. Le pasas tu tarea asíncrona y el paquete muestra un diálogo de progreso no descartable, espera el resultado, cierra el diálogo y te devuelve un resultado con tipos seguros: o bien Success con el valor, o bien Failure con el error.

El manejo de errores viene incorporado en el tipo del resultado, así que nunca se te olvida capturar una excepción.

Qué soporta

  • Diálogo MaterialshowProgressDialog muestra un indicador de progreso circular estándar de Material
  • Diálogo CupertinoshowCupertinoProgressDialog muestra un indicador de actividad al estilo iOS
  • Diálogo adaptativoshowAdaptiveProgressDialog elige automáticamente el estilo correcto para la plataforma actual
  • UI de diálogo personalizada — pasa un builder para sustituir el indicador por defecto por el widget que necesites
  • Resultados con tipos segurosProgressDialogResult<T> es una clase sellada con variantes Success y Failure, con soporte para pattern matching y métodos de conveniencia como unwrap() y map()
  • Captura de erroresFailure incluye tanto el objeto de error como la traza de pila

Casos de uso reales

Procesamiento de pagos

Una pantalla de checkout llama a la API de una pasarela de pago. Sin un diálogo de progreso, los usuarios vuelven a pulsar «Pagar» cuando parece que no pasa nada, lo que provoca cargos duplicados. Con showProgressDialog, el diálogo permanece en pantalla y bloquea la interacción hasta que la pasarela responde; luego haces pattern matching del resultado para navegar a una pantalla de confirmación o de error.

Subida de archivos

Un escáner de documentos sube imágenes a un servidor. La subida puede tardar varios segundos con conexiones lentas. Envolverla en showAdaptiveProgressDialog da a los usuarios una respuesta visual inmediata y garantiza que el diálogo encaje con la plataforma: Material en Android, Cupertino en iOS.

Envío de formularios

Un formulario de varios pasos envía datos a un backend en el último paso. Usar el diálogo de progreso evita el doble envío y te da un resultado Success/Failure limpio para decidir si mostrar una pantalla de éxito o un mensaje de error en línea.

Sincronización de datos en segundo plano

Una app de CRM sincroniza cambios locales con un servidor remoto. Un builder personalizado puede mostrar una animación de carga de marca en lugar del spinner por defecto, manteniendo la experiencia coherente con el resto de la app.

Cómo empezar

Instala el paquete:

flutter pub add flutter_future_progress_dialog

Después llama a showProgressDialog con tu tarea asíncrona:

final result = await showProgressDialog(
  context: context,
  future: () => fetchData(),
);

switch (result) {
  case Success(:final value):
    // Use the value
  case Failure(:final error):
    // Handle the error
}

Hay tres funciones de diálogo disponibles: showProgressDialog (Material), showCupertinoProgressDialog (Cupertino) y showAdaptiveProgressDialog (automática según plataforma). Todas aceptan un parámetro opcional builder para una UI personalizada.

Tienes un ejemplo completo y funcional en el directorio de ejemplos.

No. El diálogo no es descartable por defecto, lo que evita futures huérfanos y envíos duplicados. El diálogo se cierra automáticamente cuando la tarea asíncrona termina.
El diálogo se cierra y el resultado se devuelve como un Failure que contiene el error y la traza de pila. Tu código puede hacer pattern matching sobre el resultado para manejar errores sin bloques try-catch.
Sí. Usa showProgressDialog para el estilo Material, showCupertinoProgressDialog para el estilo iOS, o showAdaptiveProgressDialog para adaptarse automáticamente a la plataforma anfitriona.
Sí. Pasa un parámetro builder a cualquiera de las tres funciones de diálogo para sustituir el indicador de progreso por defecto por tu propio widget: una animación de marca, un mensaje o cualquier otro widget de Flutter.
ProgressDialogResult<T> es una clase sellada con dos variantes: Success<T>, que contiene el valor devuelto, y Failure<T>, que contiene el error y la traza de pila. Puedes usar el pattern matching de Dart o métodos de conveniencia como isSuccess, isError, unwrap() y map().