La programación asíncrona permite ejecutar tareas de forma no bloqueante, mejorando la eficiencia y la capacidad de respuesta de las aplicaciones. Dart ofrece varias herramientas para manejar operaciones asíncronas, entre las que se incluyen Futures, async, await, y streams.
Futures y Manejo de PromesasUn Future representa un valor que puede estar disponible en el futuro, ya sea porque la operación se completó con éxito o falló. Los Futures son ideales para manejar tareas que toman tiempo, como solicitudes HTTP o lecturas de archivos.
Future<String> obtenerDatos() async {
// Simulando un retraso
await Future.delayed(Duration(seconds: 2));
return 'Datos obtenidos';
}
void main() async {
String datos = await obtenerDatos();
print(datos);
// Resultado: Datos obtenidos
} Uso de async y awaitLas palabras clave async y await permiten escribir código asíncrono de manera más legible y fácil de seguir. async se utiliza para declarar que una función es asíncrona, mientras que await se usa para esperar el resultado de un Future antes de continuar.
void main() async {
print('Esperando datos...');
String datos = await obtenerDatos();
print(datos);
// Resultado: Datos obtenidos
} Los streams son una forma de manejar secuencias de datos asíncronos. Permiten recibir múltiples eventos o datos a lo largo del tiempo, como datos de un socket o actualizaciones de una base de datos.
Stream<int> contarHastaTres() async* {
for (int i = 1; i <= 3; i++) {
await Future.delayed(Duration(seconds: 1));
yield i; // Emite el valor i
}
}
void main() async {
await for (var numero in contarHastaTres()) {
print(numero);
// Resultado: 1, 2, 3 (con un segundo de espera entre cada número)
}
} Stream API en FlutterLa Stream API en Flutter permite manejar flujos de datos asíncronos, facilitando la programación reactiva y la actualización dinámica de la interfaz de usuario. A través de los streams, las aplicaciones pueden reaccionar a eventos y datos que cambian con el tiempo, como la entrada del usuario o respuestas de servicios web.
Los streams se pueden usar para gestionar eventos de usuario, como clics de botones o cambios en campos de texto. Esto permite una respuesta instantánea y eficiente en la interfaz.
StreamController<String> controlador = StreamController<String>();
void main() {
controlador.stream.listen((dato) {
print('Nuevo dato: $dato');
});
controlador.add('Evento 1');
controlador.add('Evento 2');
} Los streams son útiles para consumir datos de APIs que envían actualizaciones periódicas. Esto es ideal para aplicaciones que necesitan mostrar información en tiempo real, como feeds de redes sociales.
Stream<String> obtenerDatosDesdeAPI() async* {
// Simulando múltiples respuestas de una API
await Future.delayed(Duration(seconds: 1));
yield 'Respuesta 1';
await Future.delayed(Duration(seconds: 1));
yield 'Respuesta 2';
}
void main() async {
await for (var dato in obtenerDatosDesdeAPI()) {
print(dato);
// Resultado: Respuesta 1, Respuesta 2 (con un segundo de espera entre cada respuesta)
}
} Los streams son esenciales para actualizar la interfaz de usuario en tiempo real, como en aplicaciones de chat donde los mensajes nuevos se reciben y muestran inmediatamente.
class ChatScreen extends StatelessWidget {
final Stream<String> mensajes = Stream.periodic(Duration(seconds: 1), (count) => 'Mensaje $count');
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat')),
body: StreamBuilder<String>(
stream: mensajes,
builder: (context, snapshot) {
return ListTile(title: Text(snapshot.data ?? 'Esperando mensajes...'));
},
),
);
}
}