Sobes.tech
Middle

Come creare due thread in Dart nel contesto di Flutter?

sobes.tech AI

Risposta dell'AI

Per creare thread di esecuzione indipendenti in Dart/Flutter, si utilizzano gli Isolati. Sono compiti separati con il proprio spazio di memoria dedicato, che previene problemi di accesso concorrente ai dati e blocchi nel thread principale (thread UI).

Esistono diversi modi per creare e interagire con gli isolati:

  1. Isolate.spawn(): Il metodo a basso livello per creare un isolato. Richiede di passare una funzione di livello superiore o un metodo statico di classe da eseguire nel nuovo isolato, e una porta per scambiare messaggi.

    import 'dart:isolate';
    
    // Funzione eseguita nell'isolato
    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('Risultato dell’isolato: $message');
        isolate.kill();
      });
      print('Il thread principale continua a lavorare...');
    }
    
  2. compute(): Una funzione semplificata del pacchetto flutter/foundation, che utilizza Isolate.spawn() sotto il cofano. Ideale per compiti di background semplici che non richiedono interazioni complesse con l'isolato.

    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('Risultato dei calcoli: $result');
    }
    
  3. Isolate.spawnUri(): Usato per avviare codice da un file Dart separato in un nuovo isolato.

Interazione tra isolati:

Gli isolati scambiano dati solo tramite invio di messaggi attraverso istanze di SendPort e ReceivePort. Queste operazioni sono atomiche.

  • SendPort: Usato per inviare messaggi da un isolato all’altro.
  • ReceivePort: Usato per ascoltare i messaggi in arrivo.

Quando si trasferiscono oggetti tra isolati, devono essere "trasferibili", il che include:

  • Tipi di dati semplici (int, double, String, bool)
  • Liste e mappe contenenti tipi trasferibili
  • Alcuni tipi specifici di Flutter che possono essere serializzati

Gli oggetti non trasferibili saranno copiati, e le loro modifiche successive in un isolato non si rifletteranno nell’altro.

Punti chiave:

  • Gli isolati non possono accedere direttamente alla memoria dell’altro.
  • Gli isolati non hanno accesso allo stato condiviso, inclusi variabili, classi e widget dell’isolato principale (thread UI).
  • La comunicazione tra isolati avviene in modo asincrono.
  • Quando si lavora con gli isolati in Flutter, è importante gestire correttamente il loro ciclo di vita (ad esempio, usare isolate.kill() se necessario).

L’uso degli isolati consente di eseguire operazioni lunghe o intensive in risorse in background, evitando che l’interfaccia utente si blocchi e garantendo un funzionamento fluido dell’app.