Sobes.tech
Middle

¿Qué es un Completer en Dart y cómo se puede usar en el desarrollo con Flutter?

sobes.tech AI

Respuesta de la IA

Completer es una clase en la biblioteca dart:async que permite crear un Future y completarlo más tarde con un valor o un error. Es útil cuando una operación asíncrona no devuelve un Future directamente, pero puede ser notificada sobre su finalización.

import 'dart:async';

void main() async {
  final completer = Completer<String>(); // Crear un Completer para Future<String>

  // Simulación de una operación asíncrona
  Future.delayed(Duration(seconds: 2), () {
    // Completar el Future con un valor exitoso
    completer.complete("¡Operación completada con éxito!");
    // completer.completeError(StateError("¡Algo salió mal!")); // O con un error
  });

  print("Esperando a que la operación termine...");

  try {
    // Obtener el Future del Completer y esperar a que se complete
    final result = await completer.future;
    print("Resultado: $result");
  } catch (e) {
    print("Ocurrió un error: $e");
  }
}

En Flutter, Completer se usa a menudo para:

  • Integración con API nativas: Cuando el código nativo llama a un callback al finalizar una operación, se puede usar Completer para convertir esto en un Future en Dart.
  • Implementación de operaciones asíncronas personalizadas: Si necesitas crear una función asíncrona que no use APIs existentes que devuelvan Future.
  • Interacción entre isolates: Para señalizar la finalización de trabajo en otro isolate.

Ejemplo de uso en Flutter con API nativa (hipotético):

import 'dart:async';
import 'package:flutter/services.dart';

class NativeService {
  static const platform = MethodChannel('com.example/native_service');

  Future<String> performNativeOperation() async {
    final completer = Completer<String>();

    try {
      final result = await platform.invokeMethod('startOperation');

      // Se supone que el código nativo llamará al método 'operationCompleted'
      // con el resultado o error, y escuchamos esas llamadas.
      platform.setMethodCallHandler((call) async {
        if (call.method == 'operationCompleted') {
          if (call.arguments is String) {
            completer.complete(call.arguments as String);
          } else if (call.arguments is PlatformException) {
            completer.completeError(call.arguments as PlatformException);
          } else {
            completer.completeError(StateError("Resultado nativo desconocido"));
          }
          // Eliminar el handler si ya no es necesario
          platform.setMethodCallHandler(null);
        }
        return true; // Indica que la llamada fue manejada
      });

    } on PlatformException catch (e) {
      completer.completeError(e);
    }

    return completer.future; // Devolver el Future que se completará más tarde
  }
}

// En un widget u otro lugar:
// final service = NativeService();
// try {
//   final nativeResult = await service.performNativeOperation();
//   print("Resultado nativo: $nativeResult");
// } catch (e) {
//   print("Error en operación nativa: $e");
// }