Sobes.tech
Middle

Kaip sukurti du srautus Dart kalboje Flutter kontekste?

sobes.tech AI

Atsakymas iš AI

Dart/Flutter naudojami izoliatoriai (Isolates) kuriant nepriklausomas vykdymo srautus. Jie yra atskiri užduočių vienetai su savo atminties erdve, kas užkerta kelią konkurencinio prieigos prie duomenų ir pagrindinio srauto (UI srauto) užblokavimo problemoms.

Yra keli būdai kurti ir sąveikauti su izoliatoriais:

  1. Isolate.spawn(): žemiausio lygio būdas kurti izoliatorių. Reikalauja perduoti viršutinės lygio funkciją arba statinį klasės metodą, kuris vykdomas naujame izoliatoriuje, ir prievadą duomenų mainams.

    import 'dart:isolate';
    
    // Funkcija, vykdoma izoliatoriuje
    void isolateEntry(SendPort sendPort) {
      // Atlikti ilgą operaciją
      int result = 0;
      for (int i = 0; i < 1000000000; i++) {
        result += i;
      }
      // Grąžinti rezultatą atgal pagrindiniam izoliatoriui
      sendPort.send(result);
    }
    
    void main() async {
      ReceivePort receivePort = ReceivePort();
      // Sukurti naują izoliatorių
      Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort);
    
      // Klausytis žinučių iš izoliatoriaus
      receivePort.listen((message) {
        print('Rezultatas iš izoliatoriaus: $message');
        // Nutraukti izoliatorių gavus žinutę
        isolate.kill();
      });
    
      print('Pagrindinis srautas tęsia darbą...');
    }
    
  2. compute(): paprasta funkcija iš flutter/foundation paketo, kuri naudoja Isolate.spawn() po kapotu. Idealiai tinka paprastoms foninėms užduotims, kurioms nereikia sudėtingos sąveikos su izoliatoriumi.

    import 'package:flutter/foundation.dart';
    
    // Funkcija, vykdoma naudojant compute
    int heavyComputation(int limit) {
      int result = 0;
      for (int i = 0; i < limit; i++) {
        result += i;
      }
      return result;
    }
    
    void main() async {
      print('Pradedame sunkius skaičiavimus fonu...');
      // Vykdyti funkciją atskirame izoliatoriuje
      int result = await compute(heavyComputation, 1000000000);
      print('Skaičiavimų rezultatas: $result');
      print('Pagrindinis srautas tęsia darbą po skaičiavimų.');
    }
    
  3. Isolate.spawnUri(): naudojamas paleisti kodą iš atskiro dart failo naujame izoliatoriuje.

Sąveika tarp izoliatorių:

Izoliatoriai keičiasi duomenimis tik per žinučių perdavimą naudojant SendPort ir ReceivePort pavyzdžius. Tai atomarinės operacijos, nereikalaujančios užraktų ar kitų sinchronizacijos mechanizmų.

  • SendPort: naudojamas žinučių siuntimui iš vieno izoliatoriaus į kitą.
  • ReceivePort: naudojamas gaunamų žinučių klausymui.

Perduodant objektus tarp izoliatorių, jie turi būti "perduodami" (transferable), įskaitant:

  • Paprastus duomenų tipus (int, double, String, bool)
  • Sąrašus ir žemėlapius, turinčius perduodamus tipus
  • Kai kuriuos Flutter specifinius tipus, kurie gali būti serializuojami

Objektai, kurie nėra perduodami, bus kopijuojami, ir jų vėlesnės pakeitimai viename izoliatoriuje neatsispindės kitame.

Pagrindiniai punktai:

  • Izoliatoriai negali tiesiogiai prieiti vienas prie kito atminties.
  • Izoliatoriai neturi prieigos prie bendros būsenos, įskaitant kintamuosius, klases ir widget'us pagrindiniame izoliatoriuje (UI sraute).
  • Sąveika tarp izoliatorių vyksta asinchroniškai.
  • Darbant su izoliatoriais Flutter, svarbu teisingai valdyti jų gyvavimo ciklą (pvz., naudoti isolate.kill() jei reikia).

Izoliatorių naudojimas leidžia vykdyti ilgalaikes arba išteklius reikalaujančias operacijas fonu, užkertant kelią vartotojo sąsajos užšalimui ir užtikrinant sklandų programos veikimą.