Sobes.tech
Middle

Czym jest Completer w Dart i jak można go używać w rozwoju Flutter?

sobes.tech AI

Odpowiedź od AI

Completer to klasa w bibliotece dart:async, która pozwala na utworzenie Future i późniejsze jego ukończenie z wartością lub błędem. Jest przydatny, gdy operacja asynchroniczna nie zwraca bezpośrednio Future, ale można ją powiadomić o jej zakończeniu.

import 'dart:async';

void main() async {
  final completer = Completer<String>(); // Tworzymy Completer dla Future<String>

  // Symulacja operacji asynchronicznej
  Future.delayed(Duration(seconds: 2), () {
    // Ukończ Future z wartością sukcesu
    completer.complete("Operacja zakończona pomyślnie!");
    // completer.completeError(StateError("Coś poszło nie tak!")); // Lub z błędem
  });

  print("Oczekiwanie na zakończenie operacji...");

  try {
    // Uzyskaj Future z Completer i poczekaj na jego zakończenie
    final result = await completer.future;
    print("Wynik: $result");
  } catch (e) {
    print("Wystąpił błąd: $e");
  }
}

W Flutter Completer jest często używany do:

  • Integracji z natywnymi API: Gdy natywny kod wywołuje callback po zakończeniu operacji, można użyć Completer do przekształcenia tego w Future w Dart.
  • Implementacji własnych operacji asynchronicznych: Jeśli chcesz utworzyć funkcję asynchroniczną, która nie korzysta z istniejących API zwracających Future.
  • Interakcji między izolami: Do sygnalizacji zakończenia pracy w innym izolatcie.

Przykład użycia w Flutter z hipotetycznym API natywnym:

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

      // Zakłada się, że kod natywny wywoła metodę 'operationCompleted'
      // z wynikiem lub błędem, i nasłuchujemy te wywołania.
      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("Nieznany wynik operacji natywnej"));
          }
          // Usunięcie obsługi, jeśli nie jest już potrzebne
          platform.setMethodCallHandler(null);
        }
        return true; // Zaznacza, że wywołanie zostało obsłużone
      });

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

    return completer.future; // Zwraca Future, które zostanie ukończone później
  }
}

// W widżecie lub innym miejscu:
// final service = NativeService();
// try {
//   final nativeResult = await service.performNativeOperation();
//   print("Wynik natywny: $nativeResult");
// } catch (e) {
//   print("Błąd operacji natywnej: $e");
// }