Como criar dois threads em Dart no contexto do Flutter?
sobes.tech IA
Resposta da IA
Para criar threads de execução independentes em Dart/Flutter, usam-se Isolates. São tarefas separadas com seu próprio espaço de memória dedicado, o que previne problemas de acesso concorrente aos dados e bloqueios na thread principal (thread UI).
Existem várias formas de criar e interagir com os isolados:
-
Isolate.spawn(): A forma de baixo nível para criar um isolamento. Requer passar uma função de nível superior ou um método estático de classe para executar no novo isolamento, bem como uma porta para trocar mensagens.import 'dart:isolate'; // Função que é executada no isolamento void isolateEntry(SendPort sendPort) { // Executa alguma operação longa int result = 0; for (int i = 0; i < 1000000000; i++) { result += i; } // Envia o resultado de volta ao isolamento principal sendPort.send(result); } void main() async { ReceivePort receivePort = ReceivePort(); // Cria um novo isolamento Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort); // Ouve as mensagens do isolamento receivePort.listen((message) { print('Resultado do isolamento: $message'); // Encerra o isolamento após receber a mensagem isolate.kill(); }); print('O thread principal continua a trabalhar...'); } -
compute(): Função simplificada do pacoteflutter/foundation, que usaIsolate.spawn()por baixo dos panos. Ideal para tarefas de fundo simples que não requerem interação complexa com o isolamento.import 'package:flutter/foundation.dart'; // Função que é executada com compute int heavyComputation(int limit) { int result = 0; for (int i = 0; i < limit; i++) { result += i; } return result; } void main() async { print('Começando cálculos pesados em segundo plano...'); // Executa a função em um isolamento separado int result = await compute(heavyComputation, 1000000000); print('Resultado dos cálculos: $result'); print('O thread principal continua após os cálculos.'); } -
Isolate.spawnUri(): Usado para executar código de um arquivodartseparado em um novo isolamento.
Interação entre isolados:
Os isolados trocam dados apenas por meio de envio de mensagens através de instâncias de SendPort e ReceivePort. Essas operações são atômicas, sem necessidade de bloqueios ou outros mecanismos de sincronização.
SendPort: Usado para enviar mensagens de um isolamento para outro.ReceivePort: Usado para ouvir mensagens recebidas.
Ao transferir objetos entre isolados, eles devem ser "transferíveis", o que inclui:
- Tipos de dados simples (int, double, String, bool)
- Listas e mapas contendo tipos transferíveis
- Alguns tipos específicos do Flutter que podem ser serializados
Objetos que não são transferíveis serão copiados, e suas alterações posteriores em um isolamento não serão refletidas no outro.
Pontos-chave:
- Os isolados não podem acessar diretamente a memória um do outro.
- Os isolados não têm acesso a estado compartilhado, incluindo variáveis, classes e widgets do isolamento principal (thread UI).
- A comunicação entre isolados é assíncrona.
- Ao trabalhar com isolados no Flutter, é importante gerenciar corretamente seu ciclo de vida (por exemplo, usar
isolate.kill()se necessário).
O uso de isolados permite realizar operações longas ou intensivas em recursos em segundo plano, evitando que a interface do usuário congele e garantindo um funcionamento fluido do aplicativo.