Sobes.tech
Middle

Was ist ein Completer in Dart und wie kann er in der Flutter-Entwicklung verwendet werden?

sobes.tech KI

Antwort von AI

Completer ist eine Klasse in der Bibliothek dart:async, die es ermöglicht, ein Future zu erstellen und es später mit einem Wert oder Fehler abzuschließen. Es ist nützlich, wenn eine asynchrone Operation nicht direkt ein Future zurückgibt, aber darüber benachrichtigt werden kann.

import 'dart:async';

void main() async {
  final completer = Completer<String>(); // Erstellen eines Completers für Future<String>

  // Simulation einer asynchronen Operation
  Future.delayed(Duration(seconds: 2), () {
    // Abschließen des Futures mit einem Erfolgswert
    completer.complete("Operation erfolgreich abgeschlossen!");
    // completer.completeError(StateError("Etwas ist schief gelaufen!")); // Oder mit Fehler
  });

  print("Warten auf Abschluss der Operation...");

  try {
    // Das Future vom Completer holen und auf Abschluss warten
    final result = await completer.future;
    print("Ergebnis: $result");
  } catch (e) {
    print("Ein Fehler ist aufgetreten: $e");
  }
}

In Flutter wird Completer häufig verwendet für:

  • Integration mit nativen APIs: Wenn nativer Code einen Callback aufruft, wenn eine Operation abgeschlossen ist, kann Completer verwendet werden, um dies in ein Future in Dart umzuwandeln.
  • Implementierung benutzerdefinierter asynchroner Operationen: Wenn eine asynchrone Funktion erstellt werden soll, die keine bestehenden Future-APIs nutzt.
  • Interaktion zwischen Isolaten: Um das Ende der Arbeit in einem anderen Isolat zu signalisieren.

Beispiel für die Verwendung in Flutter mit einer hypothetischen nativen API:

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

      // Es wird angenommen, dass der native Code die Methode 'operationCompleted' aufruft
      // mit dem Ergebnis oder Fehler, und wir hören diese Aufrufe.
      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("Unbekanntes natives Ergebnis"));
          }
          // Handler entfernen, wenn nicht mehr benötigt
          platform.setMethodCallHandler(null);
        }
        return true; // Signalisiert, dass der Aufruf verarbeitet wurde
      });

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

    return completer.future; // Gibt das Future zurück, das später abgeschlossen wird
  }
}

// In einem Widget oder an anderer Stelle:
// final service = NativeService();
// try {
//   final nativeResult = await service.performNativeOperation();
//   print("Natives Ergebnis: $nativeResult");
// } catch (e) {
//   print("Fehler bei nativer Operation: $e");
// }