Sobes.tech
Middle

Kako kreirati dva niti u Dart-u u kontekstu Flutter-a?

sobes.tech АИ

Одговор од АИ

U Dart/Flutter-u, izolati (Isolates) se koriste za kreiranje nezavisnih tokova izvršavanja. Oni predstavljaju odvojene zadatke sa sopstvenim memorijskim prostorom, što sprečava probleme sa konkurentnim pristupom podacima i blokiranje glavnog toka (UI toka).

Postoji nekoliko načina za kreiranje i interakciju sa izolatom:

  1. Isolate.spawn(): Najniži nivo za kreiranje izolata. Zahteva prosleđivanje funkcije višeg nivoa ili statičke metode klase za izvršenje u novom izolatu i porta za razmenu poruka.

    import 'dart:isolate';
    
    // Funkcija koja se izvršava u izolatu
    void isolateEntry(SendPort sendPort) {
      // Izvršavamo neku dugu operaciju
      int result = 0;
      for (int i = 0; i < 1000000000; i++) {
        result += i;
      }
      // Šaljemo rezultat nazad glavnom izolatu
      sendPort.send(result);
    }
    
    void main() async {
      ReceivePort receivePort = ReceivePort();
      // Kreiramo novi izolat
      Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort);
    
      // Slušamo poruke od izolata
      receivePort.listen((message) {
        print('Rezultat iz izolata: $message');
        // Zaustavljamo izolata nakon primanja poruke
        isolate.kill();
      });
    
      print('Glavni tok nastavlja rad...');
    }
    
  2. compute(): Pojednostavljena funkcija iz paketa flutter/foundation, koja koristi Isolate.spawn() u pozadini. Idealan je za jednostavne pozadinske zadatke koji ne zahtevaju složenu interakciju sa izolatom.

    import 'package:flutter/foundation.dart';
    
    // Funkcija koja se izvršava pomoću compute
    int heavyComputation(int limit) {
      int result = 0;
      for (int i = 0; i < limit; i++) {
        result += i;
      }
      return result;
    }
    
    void main() async {
      print('Počinju teški računi u pozadini...');
      // Izvršavamo funkciju u posebnom izolatu
      int result = await compute(heavyComputation, 1000000000);
      print('Rezultat računanja: $result');
      print('Glavni tok nastavlja rad nakon računanja.');
    }
    
  3. Isolate.spawnUri(): Koristi se za pokretanje koda iz posebnog fajla dart u novom izolatu.

Interakcija između izolata:

Izolati razmenjuju podatke samo putem poruka preko instanci SendPort i ReceivePort. To su atomarne operacije koje ne zahtevaju blokade ili druge mehanizme za sinhronizaciju.

  • SendPort: Koristi se za slanje poruka iz jednog izolata u drugi.
  • ReceivePort: Koristi se za slušanje dolaznih poruka.

Prilikom prenosa objekata između izolata, oni moraju biti "prenosiivi" (transferable), što uključuje:

  • Jednostavne tipove podataka (int, double, String, bool)
  • Liste i mape koje sadrže prenosiive tipove
  • Neke specifične Flutter tipove koje je moguće serializovati

Objekti koji nisu prenosiivi biće kopirani, a njihove kasnije izmene u jednom izolatu neće se odraziti u drugom.

Ključne tačke:

  • Izolati ne mogu direktno pristupati memoriji drugih.
  • Nemaju pristup zajedničkom stanju, uključujući promenljive, klase i widget-e glavnog izolata (UI toka).
  • Komunikacija između izolata odvija se asinhrono.
  • U Flutter-u je važno pravilno upravljati njihovim životnim ciklusom (npr. korišćenjem isolate.kill() ako je potrebno).

Korišćenje izolata omogućava izvršavanje dugotrajnih ili resursno zahtevnih operacija u pozadini, sprečavajući zamrzavanje korisničkog interfejsa i obezbeđujući glatko funkcionisanje aplikacije.