Sobes.tech
Middle

¿Cómo crear dos hilos en Dart en el contexto de Flutter?

sobes.tech AI

Respuesta de la IA

Para crear hilos de ejecución independientes en Dart/Flutter, se utilizan Aislas (Isolates). Son tareas separadas con su propio espacio de memoria dedicado, lo que previene problemas de acceso concurrente a los datos y bloqueos en el hilo principal (hilo UI).

Existen varias formas de crear e interactuar con los aislas:

  1. Isolate.spawn(): La forma de bajo nivel para crear un aislamiento. Requiere pasar una función de nivel superior o un método estático de clase para ejecutar en el nuevo aislamiento y un puerto para intercambiar mensajes.

    import 'dart:isolate';
    
    // Función que se ejecuta en el aislamiento
    void isolateEntry(SendPort sendPort) {
      // Realiza alguna operación larga
      int result = 0;
      for (int i = 0; i < 1000000000; i++) {
        result += i;
      }
      // Envía el resultado de vuelta al aislamiento principal
      sendPort.send(result);
    }
    
    void main() async {
      ReceivePort receivePort = ReceivePort();
      // Crea un nuevo aislamiento
      Isolate isolate = await Isolate.spawn(isolateEntry, receivePort.sendPort);
    
      // Escucha los mensajes del aislamiento
      receivePort.listen((message) {
        print('Resultado del aislamiento: $message');
        // Finaliza el aislamiento después de recibir el mensaje
        isolate.kill();
      });
    
      print('El hilo principal continúa trabajando...');
    }
    
  2. compute(): Función simplificada del paquete flutter/foundation, que usa Isolate.spawn() internamente. Es ideal para tareas de fondo simples que no requieren interacción compleja con el aislamiento.

    import 'package:flutter/foundation.dart';
    
    // Función que se ejecuta con compute
    int heavyComputation(int limit) {
      int result = 0;
      for (int i = 0; i < limit; i++) {
        result += i;
      }
      return result;
    }
    
    void main() async {
      print('Comenzando cálculos pesados en segundo plano...');
      // Ejecuta la función en un aislamiento separado
      int result = await compute(heavyComputation, 1000000000);
      print('Resultado de los cálculos: $result');
      print('El hilo principal continúa después de los cálculos.');
    }
    
  3. Isolate.spawnUri(): Se usa para ejecutar código desde un archivo dart separado en un nuevo aislamiento.

Interacción entre aislas:

Los aislas intercambian datos solo mediante envío de mensajes a través de instancias de SendPort y ReceivePort. Estas operaciones son atómicas, sin necesidad de bloqueos u otros mecanismos de sincronización.

  • SendPort: Se usa para enviar mensajes de un aislamiento a otro.
  • ReceivePort: Se usa para escuchar mensajes entrantes.

Al transferir objetos entre aislas, estos deben ser "transferibles", lo que incluye:

  • Tipos de datos simples (int, double, String, bool)
  • Listas y mapas que contienen tipos transferibles
  • Algunos tipos específicos de Flutter que pueden ser serializados

Los objetos que no son transferibles serán copiados, y sus cambios posteriores en un aislamiento no se reflejarán en el otro.

Puntos clave:

  • Los aislas no pueden acceder directamente a la memoria del otro.
  • Los aislas no tienen acceso a estado compartido, incluyendo variables, clases y widgets del aislamiento principal (hilo UI).
  • La comunicación entre aislas es asíncrona.
  • Al trabajar con aislas en Flutter, es importante gestionar correctamente su ciclo de vida (por ejemplo, usar isolate.kill() si es necesario).

El uso de aislas permite realizar operaciones prolongadas o intensivas en recursos en segundo plano, evitando que la interfaz de usuario se congele y asegurando un funcionamiento fluido de la aplicación.