Ako vytvoriť dva vlákna v Dart v kontexte Flutter?
sobes.tech AI
Odpoveď od AI
V Dart/Flutter sa se za kreiranje nezávislých tokov vykonávania používajú izoláty (Isolates). Predstavujú samostatné úlohy s vlastným vyhradeným priestorom pamäte, čo zabraňuje problémom s konkurenčným prístupom k údajom a blokovaniu hlavného vlákna (UI vlákna).
Existuje niekoľko spôsobov, ako vytvárať a komunikovať s izolátmi:
-
Isolate.spawn(): Najnižšia úroveň vytvárania izolátu. Vyžaduje odovzdanie funkcie vyššej úrovne alebo statickej metódy triedy na vykonanie v novom izoláte a portu na výmenu správ.import 'dart:isolate'; // Funkcia, ktorá sa vykonáva v izoláte void isolateEntry(SendPort sendPort) { // Vykonávame nejakú dlhú operáciu int result = 0; for (int i = 0; i < 1000000000; i++) { result += i; } // Odosielame výsledok späť hlavného izolátu sendPort.send(result); } void main() async { ReceivePort receivePort = ReceivePort(); // Vytvorenie nového izolátu Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort); // Počúvame správy od izolátu receivePort.listen((message) { print('Výsledok z izolátu: $message'); // Ukončíme izolát po prijatí správy isolate.kill(); }); print('Hlavný tok pokračuje v práci...'); } -
compute(): Zjednodušená funkcia z balíkaflutter/foundation, ktorá používaIsolate.spawn()na pozadí. Ideálna pre jednoduché úlohy na pozadí, ktoré nevyžadujú zložitú komunikáciu s izolátom.import 'package:flutter/foundation.dart'; // Funkcia, ktorá sa vykonáva pomocou compute int heavyComputation(int limit) { int result = 0; for (int i = 0; i < limit; i++) { result += i; } return result; } void main() async { print('Začíname ťažké výpočty na pozadí...'); // Spúšťame funkciu v samostatnom izoláte int result = await compute(heavyComputation, 1000000000); print('Výsledok výpočtov: $result'); print('Hlavný tok pokračuje po výpočtoch.'); } -
Isolate.spawnUri(): Používa sa na spustenie kódu z samostatného súborudartv novom izoláte.
Interakcia medzi izolátmi:
Izoláty si vymieňajú údaje iba prostredníctvom odosielania správ cez inštancie SendPort a ReceivePort. Ide o atomárne operácie, ktoré nevyžadujú zámky alebo iné mechanizmy na synchronizáciu.
SendPort: Používa sa na odosielanie správ z jedného izolátu do druhého.ReceivePort: Používa sa na sledovanie prichádzajúcich správ.
Pri prenose objektov medzi izolátmi musia byť objekty "prenášateľné" (transferable), čo zahŕňa:
- Jednoduché dátové typy (int, double, String, bool)
- Zoznamy a mapy obsahujúce prenášateľné typy
- Niektoré špecifické typy Flutteru, ktoré je možné serializovať
Objekty, ktoré nie sú prenášateľné, budú skopírované a ich následné zmeny v jednom izoláte sa neprejavia v inom.
Kľúčové body:
- Izoláty nemôžu priamo pristupovať k pamäti iných.
- Nemajú prístup k spoločnému stavu, vrátane premenných, tried a widgetov hlavného izolátu (UI vlákna).
- Komunikácia medzi izolátmi prebieha asynchrónne.
- V Flutteri je dôležité správne spravovať ich životný cyklus (napríklad použitím
isolate.kill()ak je to potrebné).
Použitie izolátov umožňuje vykonávanie dlhých alebo zdrojovo náročných operácií na pozadí, čím sa zabraňuje zaseknutiu používateľského rozhrania a zabezpečuje plynulý chod aplikácie.