Jak vytvořit dva vlákna v Dart v kontextu Flutter?
sobes.tech AI
Odpověď od AI
V Dart/Flutter se pro vytváření nezávislých toků provádění používají izoláty (Isolates). Ty představují samostatné úlohy s vlastním vyhrazeným prostorem paměti, což zabraňuje problémům s konkurenčním přístupem k datům a blokování hlavního vlákna (UI vlákna).
Existuje několik způsobů, jak vytvářet a komunikovat s izoláty:
-
Isolate.spawn(): Nejnižší úroveň vytváření izolátu. Vyžaduje předání funkce vyšší úrovně nebo statické metody třídy, která se má vykonat v novém izolátu, a portu pro výměnu zpráv.import 'dart:isolate'; // Funkce, která se vykonává v izolátu void isolateEntry(SendPort sendPort) { // Provádíme nějakou dlouhou operaci int result = 0; for (int i = 0; i < 1000000000; i++) { result += i; } // Odesíláme výsledek zpět hlavnímu izolátu sendPort.send(result); } void main() async { ReceivePort receivePort = ReceivePort(); // Vytvoření nového izolátu Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort); // Posloucháme zprávy od izolátu receivePort.listen((message) { print('Výsledek z izolátu: $message'); // Ukončíme izolát po obdržení zprávy isolate.kill(); }); print('Hlavní vlákno pokračuje v práci...'); } -
compute(): Zjednodušená funkce z balíčkuflutter/foundation, která používáIsolate.spawn()na pozadí. Ideální pro jednoduché úlohy na pozadí, které nevyžadují složitou komunikaci s izolátem.import 'package:flutter/foundation.dart'; // Funkce, která se vykonává pomocí compute int heavyComputation(int limit) { int result = 0; for (int i = 0; i < limit; i++) { result += i; } return result; } void main() async { print('Začínáme těžké výpočty na pozadí...'); // Spouštíme funkci v samostatném izolátu int result = await compute(heavyComputation, 1000000000); print('Výsledek výpočtů: $result'); print('Hlavní vlákno pokračuje po výpočtech.'); } -
Isolate.spawnUri(): Používá se ke spuštění kódu z samostatného souborudartv novém izolátu.
Interakce mezi izoláty:
Izoláty si vyměňují data pouze prostřednictvím odesílání zpráv přes instance SendPort a ReceivePort. Jedná se o atomické operace, které nevyžadují zámky nebo jiné synchronizační mechanismy.
SendPort: Používá se k odesílání zpráv z jednoho izolátu do druhého.ReceivePort: Používá se ke sledování příchozích zpráv.
Při přenosu objektů mezi izoláty musí být objekty "přenášitelné" (transferable), což zahrnuje:
- Jednoduché datové typy (int, double, String, bool)
- Seznamy a mapy obsahující přenášitelné typy
- Některé specifické typy Flutteru, které lze serializovat
Objekty, které nejsou přenášitelné, budou zkopírovány a jejich následné změny v jednom izolátu se neprojeví v jiném.
Klíčové body:
- Izoláty nemohou přímo přistupovat k paměti druhého.
- Nemají přístup ke sdílenému stavu, včetně proměnných, tříd a widgetů hlavního izolátu (UI vlákna).
- Komunikace mezi izoláty probíhá asynchronně.
- Při práci s izoláty v Flutteru je důležité správně spravovat jejich životní cyklus (například použitím
isolate.kill()podle potřeby).
Použití izolátů umožňuje provádět dlouhotrvající nebo náročné operace na pozadí, čímž se předchází zaseknutí uživatelského rozhraní a zajišťuje plynulost chodu aplikace.