Flutter之多线程2025-07-07 周一

在 Flutter 和 Dart 里,由于单线程执行模型的存在,若要实现多线程操作,需借助Isolate。

使用 compute 函数(适用于简单场景)

compute函数能够把耗时任务放到后台 Isolate 中执行,特别适合处理简单的计算任务。

  • 自动管理 Isolate:无需手动创建和销毁 Isolate,系统会自动处理。
  • 简化数据传递:借助函数参数和返回值实现数据传递,无需手动管理SendPort。
  • 类型安全:支持泛型,确保输入输出类型的一致性。
  • 必须是顶级或静态函数:回调函数(如上述示例中的isPrime)必须是顶级函数或者类的静态方法,这是因为 Isolate 需要独立于 UI 线程运行。
  • 自动错误处理:如果后台任务抛出异常,compute会将异常传递给调用方,可通过try-catch捕获。
  • 适用于简单任务:适合执行单次的计算任务,例如 JSON 解析、图片处理、数学运算等。
  • 数据传递限制:参数和返回值必须是可序列化的对象(如基本数据类型、列表、映射等)。
import 'package:flutter/foundation.dart';
import 'dart:math';

// 顶级函数:判断素数(耗时操作)
bool isPrime(int number) {
  if (number <= 1) return false;
  for (int i = 2; i <= sqrt(number); i++) {
    if (number % i == 0) return false;
  }
  return true;
}

class PrimeChecker extends StatefulWidget {
  @override
  _PrimeCheckerState createState() => _PrimeCheckerState();
}

class _PrimeCheckerState extends State<PrimeChecker> {
  bool? _isPrime;
  bool _isLoading = false;

  Future<void> _checkPrime(int number) async {
    setState(() => _isLoading = true);
    
    // 在后台Isolate执行计算
    final result = await compute(isPrime, number);
    
    setState(() {
      _isPrime = result;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () => _checkPrime(123456789),
          child: Text('检查是否为素数'),
        ),
        if (_isLoading) CircularProgressIndicator()
        else if (_isPrime != null)
          Text('$(_isPrime! ? '是' : '不是') 素数'),
      ],
    );
  }
}

2. 使用Isolate.run()

简化语法,适合快速执行独立任务。

void main() async {
  final result = await Isolate.run(() {
    // 耗时操作(自动在新Isolate中执行)
    return heavyTask();
  });
  
  print('异步结果: $result');
}

int heavyTask() {
  // 模拟耗时计算
  return 42;
}

3. 手动创建 Isolate(完整版)

适用于复杂场景,需手动管理生命周期和通信。

import 'dart:isolate';

void main() async {
  // 1. 创建接收端口(用于接收消息)
  final receivePort = ReceivePort();
  
  // 2. 启动新Isolate,传入入口函数和发送端口
  final isolate = await Isolate.spawn(
    workerFunction,       // 入口函数(必须是顶级或静态方法)
    receivePort.sendPort, // 发送端口,用于传递消息
  );
  
  // 3. 监听消息
  receivePort.listen((message) {
    print('收到消息: $message');
    
    // 任务完成后销毁Isolate
    isolate.kill(priority: Isolate.immediate);
    receivePort.close();
  });
}

// 新Isolate的入口函数
void workerFunction(SendPort sendPort) {
  // 执行耗时操作
  int result = 0;
  for (int i = 0; i < 1000000; i++) {
    result += i;
  }
  
  // 发送结果回主Isolate
  sendPort.send('计算结果: $result');
}

使用例子

文件处理(如大文件解析)

使用手动 Isolate 解析大型 JSON 文件:

import 'dart:io';
import 'dart:isolate';
import 'dart:convert';

void main() async {
  final receivePort = ReceivePort();
  await Isolate.spawn(
    parseJsonFile,
    {'path': 'large_file.json', 'sendPort': receivePort.sendPort},
  );

  receivePort.listen((data) {
    print('解析完成,数据长度: ${data.length}');
    receivePort.close();
  });
}

// 新Isolate中执行文件解析
void parseJsonFile(dynamic message) {
  final String path = message['path'];
  final SendPort sendPort = message['sendPort'];

  try {
    final file = File(path);
    final jsonString = file.readAsStringSync();
    final parsedData = json.decode(jsonString);
    sendPort.send(parsedData);
  } catch (e) {
    sendPort.send(null);
  }
}

图像处理(如滤镜应用)

在后台线程处理图像数据:

import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';

// 应用灰度滤镜(耗时操作)
Future<ui.Image> applyGrayscale(ui.Image image) async {
  return await compute(_processImage, image);
}

// 必须是顶级函数
ui.Image _processImage(ui.Image image) {
  // 创建图像处理器
  final completer = Completer<ui.Image>();
  
  // 获取图像数据
  image.toByteData(format: ui.ImageByteFormat.rawRgba).then((byteData) {
    if (byteData == null) return;
    
    final buffer = byteData.buffer;
    final length = buffer.lengthInBytes;
    
    // 应用灰度滤镜(修改每个像素)
    for (int i = 0; i < length; i += 4) {
      final r = buffer.asUint8List()[i];
      final g = buffer.asUint8List()[i + 1];
      final b = buffer.asUint8List()[i + 2];
      
      // 计算灰度值
      final gray = (r * 0.299 + g * 0.587 + b * 0.114).toInt();
      
      // 应用到RGB通道
      buffer.asUint8List()[i] = gray;
      buffer.asUint8List()[i + 1] = gray;
      buffer.asUint8List()[i + 2] = gray;
    }
    
    // 创建处理后的图像
    ui.decodeImageFromPixels(
      buffer.asUint8List(),
      image.width,
      image.height,
      ui.PixelFormat.rgba8888,
      (processedImage) => completer.complete(processedImage),
    );
  });
  
  return completer.future;
}

持续后台任务(如进度监控)

使用手动 Isolate 实现进度监控:

import 'dart:isolate';

class ProgressMonitor {
  late Isolate _isolate;
  final ReceivePort _receivePort = ReceivePort();
  final void Function(double progress) onProgress;

  ProgressMonitor({required this.onProgress});

  Future<void> start() async {
    _isolate = await Isolate.spawn(
      _monitorProgress,
      _receivePort.sendPort,
    );
    
    _receivePort.listen((message) {
      if (message is double) {
        onProgress(message);
      }
    });
  }

  void stop() {
    _isolate.kill();
    _receivePort.close();
  }

  // 独立Isolate中运行的进度监控
  static void _monitorProgress(SendPort sendPort) {
    double progress = 0.0;
    while (progress < 1.0) {
      // 模拟进度更新
      progress += 0.01;
      sendPort.send(progress);
      sleep(Duration(milliseconds: 100));
    }
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容