Sobes.tech
Middle

Cos'è un Completer in Dart e come può essere utilizzato nello sviluppo Flutter?

sobes.tech AI

Risposta dell'AI

Completer è una classe nella libreria dart:async che permette di creare un Future e completarlo successivamente con un valore o un errore. È utile quando un'operazione asincrona non restituisce direttamente un Future, ma può essere notificata del suo completamento.

import 'dart:async';

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

  // Simulazione di un'operazione asincrona
  Future.delayed(Duration(seconds: 2), () {
    // Completiamo il Future con un valore di successo
    completer.complete("Operazione completata con successo!");
    // completer.completeError(StateError("Qualcosa è andato storto!")); // O con errore
  });

  print("In attesa del completamento dell'operazione...");

  try {
    // Otteniamo il Future dal Completer e aspettiamo il suo completamento
    final result = await completer.future;
    print("Risultato: $result");
  } catch (e) {
    print("Si è verificato un errore: $e");
  }
}

In Flutter, Completer viene spesso usato per:

  • Integrazione con API native: Quando il codice nativo chiama un callback al termine di un'operazione, si può usare Completer per convertirlo in un Future in Dart.
  • Implementazione di operazioni asincrone personalizzate: Se si desidera creare una funzione asincrona che non utilizza API esistenti che restituiscono Future.
  • Interazione tra isolate: Per segnalare il completamento del lavoro in un altro isolate.

Esempio di utilizzo in Flutter con API native (ipotetico):

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');

      // Si presume che il codice nativo chiamerà il metodo 'operationCompleted'
      // con il risultato o errore, e ascoltiamo queste chiamate.
      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("Risultato nativo sconosciuto"));
          }
          // Rimuovere il handler se non più necessario
          platform.setMethodCallHandler(null);
        }
        return true; // Indica che la chiamata è stata gestita
      });

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

    return completer.future; // Restituisce il Future che sarà completato più tardi
  }
}

// In un widget o altro:
// final service = NativeService();
// try {
//   final nativeResult = await service.performNativeOperation();
//   print("Risultato nativo: $nativeResult");
// } catch (e) {
//   print("Errore nell'operazione nativa: $e");
// }