Sobes.tech
Middle

Co je to Completer v Dart a jak jej lze použít ve vývoji Flutter?

sobes.tech AI

Odpověď od AI

Completer je třída v knihovně dart:async, která umožňuje vytvořit Future a dokončit jej později s nějakou hodnotou nebo chybou. Je užitečný, když asynchronní operace přímo nevrací Future, ale lze ji oznámit jejím dokončením.

import 'dart:async';

void main() async {
  final completer = Completer<String>(); // Vytvoříme Completer pro Future<String>

  // Simulace asynchronní operace
  Future.delayed(Duration(seconds: 2), () {
    // Dokončíme Future s úspěšnou hodnotou
    completer.complete("Operace úspěšně dokončena!");
    // completer.completeError(StateError("Něco se pokazilo!")); // nebo s chybou
  });

  print("Čekáme na dokončení operace...");

  try {
    // Získáme Future z Completer a počkáme na jeho dokončení
    final result = await completer.future;
    print("Výsledek: $result");
  } catch (e) {
    print("Došlo k chybě: $e");
  }
}

V Flutteru se Completer často používá pro:

  • Integraci s nativními API: Když nativní kód volá zpětné volání (callback) při dokončení operace, lze použít Completer k převodu tohoto na Future v Dart.
  • Implementaci vlastních asynchronních operací: Pokud je potřeba vytvořit asynchronní funkci, která nepoužívá existující API vracející Future.
  • Interakci mezi izoláty: Pro signalizaci dokončení práce v jiném izolátu.

Příklad použití v Flutteru s nativním API (hypotetický):

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

      // Předpokládá se, že nativní kód zavolá metodu 'operationCompleted'
      // s výsledkem nebo chybou, a my posloucháme tyto volání.
      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("Neznámý výsledek nativní operace"));
          }
          // Odstranit handler, pokud již není potřeba
          platform.setMethodCallHandler(null);
        }
        return true; // Označujeme, že volání bylo zpracováno
      });

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

    return completer.future; // Vrací Future, které bude dokončeno později
  }
}
// V widgetu nebo jinde:
// final service = NativeService();
// try {
//   final nativeResult = await service.performNativeOperation();
//   print("Nativní výsledek: $nativeResult");
// } catch (e) {
//   print("Chyba nativní operace: $e");
// }