Jak utworzyć dwa wątki w Dart w kontekście Flutter?
sobes.tech AI
Odpowiedź od AI
Aby tworzyć niezależne wątki wykonawcze w Dart/Flutter, używa się Izolatów (Isolates). Są to oddzielne zadania z własną dedykowaną przestrzenią pamięci, co zapobiega problemom z dostępem współbieżnym do danych i blokadom głównego wątku (wątku UI).
Istnieje kilka sposobów tworzenia i interakcji z izolatorami:
-
Isolate.spawn(): Niskopoziomowa metoda tworzenia izolatora. Wymaga przekazania funkcji na poziomie wyższym lub statycznej metody klasy do wykonania w nowym izolatorze oraz portu do wymiany wiadomości.import 'dart:isolate'; // Funkcja wykonywana w izolatorze void isolateEntry(SendPort sendPort) { int result = 0; for (int i = 0; i < 1000000000; i++) { result += i; } sendPort.send(result); } void main() async { ReceivePort receivePort = ReceivePort(); Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort); receivePort.listen((message) { print('Wynik z izolatora: $message'); isolate.kill(); }); print('Główny wątek kontynuuje pracę...'); } -
compute(): Uproszczona funkcja z pakietuflutter/foundation, która używaIsolate.spawn()pod maską. Idealna do prostych zadań w tle, które nie wymagają skomplikowanej interakcji z izolatem.import 'package:flutter/foundation.dart'; int heavyComputation(int limit) { int result = 0; for (int i = 0; i < limit; i++) { result += i; } return result; } void main() async { int result = await compute(heavyComputation, 1000000000); print('Wynik obliczeń: $result'); } -
Isolate.spawnUri(): Używany do uruchamiania kodu z osobnego pliku Dart w nowym izolatorze.
Interakcja między izolatorami:
Izolatory wymieniają dane tylko poprzez wysyłanie wiadomości za pomocą instancji SendPort i ReceivePort. Są to operacje atomowe.
SendPort: Używany do wysyłania wiadomości z jednego izolatora do drugiego.ReceivePort: Używany do nasłuchiwania nadchodzących wiadomości.
Podczas przesyłania obiektów między izolatorami, muszą one być "przesywalne" (transferable), co obejmuje:
- Proste typy danych (int, double, String, bool)
- Listy i mapy zawierające przesywalne typy
- Niektóre specyficzne typy Flutter, które mogą być serializowane
Obiekty, które nie są przesywalne, będą kopiowane, a ich późniejsze zmiany w jednym z izolatorów nie będą odzwierciedlone w drugim.
Kluczowe punkty:
- Izolatory nie mogą bezpośrednio odwoływać się do pamięci innych.
- Izolatory nie mają dostępu do wspólnego stanu, w tym zmiennych, klas i widżetów głównego izolatora (wątku UI).
- Komunikacja między izolatorami odbywa się asynchronicznie.
- Przy pracy z izolatorami w Flutter ważne jest odpowiednie zarządzanie ich cyklem życia (np. użycie
isolate.kill()w razie potrzeby).
Użycie izolatorów pozwala na wykonywanie długotrwałych lub zasobożernych operacji w tle, zapobiegając zawieszaniu interfejsu użytkownika i zapewniając płynne działanie aplikacji.