Isolate 有的同学不清楚他和 future 的区别,以及不知道什么时候使用合适。
文本将会介绍 isolate 特点和如何在 flutter 中实现,以及在社区 Pub 仓库中的快捷插件使用。
https://docs.flutter.dev/packages-and-plugins/background-processes
https://flutter.github.io/samples/isolate_example.html1
https://pub-web.flutter-io.cn/packages/flutter_isolate
Flutter Isolate 是 Flutter 框架提供的一种并发编程的机制,用于在应用程序中创建多个独立的执行线程,以便在后台执行一些耗时的计算任务、IO 操作或其他需要并行处理的任务。Flutter Isolate 的主要作用包括:
Flutter中的Isolate和Future都涉及到并发编程,但它们是不同的概念。
Isolate是一种轻量级的线程,它可以独立于主线程运行。Isolate可以在自己的内存空间中运行代码,可以运行CPU密集型任务而不会阻塞主线程。Isolate之间是相互独立的,它们不能直接共享状态,但可以通过消息传递进行通信。在Flutter中,您可以使用compute()
方法或Isolate.spawn()
函数来创建Isolate并在其中执行代码。
Future是一种异步编程的概念,它代表一个可能在未来完成的操作。Future允许您在进行耗时操作时不会阻塞UI线程,以保持应用程序的响应性。Future通常用于在后台执行I/O操作或从网络获取数据。在Flutter中,您可以使用async/await
语法或.then()
方法来处理Future。
虽然Future是Flutter中处理异步操作的一种方式,但在某些情况下使用Isolate可以更好地满足特定的需求,而不是使用Future。以下是一些可能使用Isolate而不是Future的情况:
执行CPU密集型任务:如果您需要在后台执行CPU密集型任务,例如图像处理或音频处理,那么使用Isolate会更好,因为它可以在独立的线程中运行,而不会阻塞UI线程。使用Future可能会导致UI线程被阻塞,从而影响应用程序的响应性。
处理大量数据:如果您需要处理大量的数据,例如从网络获取大型数据集,那么使用Isolate可以更好,因为它可以在独立的线程中处理数据,而不会阻塞UI线程。使用Future可能会导致UI线程被阻塞,从而影响应用程序的响应性。
并行处理多个任务:如果您需要同时处理多个任务,例如同时下载多个文件或同时处理多个图像,那么使用Isolate可以更好,因为它可以在独立的线程中同时处理多个任务,而不会阻塞UI线程。使用Future可能需要串行处理多个任务,从而导致应用程序的响应性变差。
在Flutter中使用Isolate进行并发编程需要一些步骤。
下面是一个简单的示例,演示如何使用Isolate执行计算任务:
import 'dart:isolate'; void main() async { ReceivePort receivePort = ReceivePort(); Isolate isolate = await Isolate.spawn(worker, receivePort.sendPort); receivePort.listen((message) { print('Received result: $message'); receivePort.close(); isolate.kill(priority: Isolate.immediate); }); await Future.delayed(Duration(seconds: 1)); int result = await computeFactorial(10); isolate.kill(priority: Isolate.immediate); print('Computed result: $result'); } void worker(SendPort sendPort) { ReceivePort receivePort = ReceivePort(); sendPort.send(receivePort.sendPort); receivePort.listen((message) { int number = message as int; int result = computeFactorial(number); sendPort.send(result); }); } int computeFactorial(int number) { if (number <= 0) { return 1; } else { return number * computeFactorial(number - 1); } }
在这个示例中,我们首先使用Isolate.spawn()
函数创建了一个新的Isolate,并在其中执行worker()
函数。worker()
函数接收一个SendPort
,并创建一个ReceivePort
用于监听消息。在main()
函数中,我们创建了一个ReceivePort
用于监听来自Isolate的消息,并将其发送给Isolate的SendPort
。然后,我们使用await Future.delayed()
函数等待一秒钟,以便Isolate有足够的时间计算结果。最后,我们终止Isolate并输出计算结果。
在worker()
函数中,我们监听来自ReceivePort
的消息,并将其作为整数传递给computeFactorial()
函数。然后,我们将计算结果发送回主Isolate的SendPort
。
computeFactorial()
函数是一个简单的阶乘计算函数,它通过递归方式计算阶乘。
总之,使用Isolate进行并发编程需要创建一个新的Isolate并在其中执行任务。在Flutter中,您可以使用Isolate.spawn()
函数创建Isolate,并使用SendPort
和ReceivePort
进行消息传递。
https://pub-web.flutter-io.cn/packages/flutter_isolate
这个插件的好处就是,简化了我们的代码,而且还提供了丰富的 api 让我们更好的进行 isolate 操作。
pubspec.yaml
dependencies: ... flutter_isolate: ^2.0.4 path_provider: ^2.0.15 flutter_downloader: ^1.10.4
isolate 不支持热更新,需要重新启动调试
lib/one.dart
('vm:entry-point') void someFunction(String arg) { print("Running in an isolate with argument : $arg"); }
ElevatedButton( child: const Text('01 - 简单的执行顶层函数'), onPressed: () { FlutterIsolate.spawn(someFunction, "hello world"); }, ),
('vm:entry-point') Future<int> expensiveWork(int arg) async { int result = arg + 100; return result; }
ElevatedButton( child: const Text('02 - Compute函数'), onPressed: () async { var res = await flutterCompute(expensiveWork, 123); print(res); }, ),
准备一个显示下载进度的组件
/// markdown 视图显示 class MarkdownView extends StatelessWidget { const MarkdownView({super.key}); static void downloaderCallback(String id, int status, int progress) { print("progress: $progress"); } Widget build(BuildContext context) { return Container(); } }
下载线程函数
('vm:entry-point') void isolate2(String arg) { getTemporaryDirectory().then((dir) async { print("isolate2 temporary directory: $dir"); await FlutterDownloader.initialize(debug: true); FlutterDownloader.registerCallback(MarkdownView.downloaderCallback); final taskId = await FlutterDownloader.enqueue( url: "https://raw.githubusercontent.com/rmawatson/flutter_isolate/master/README.md", savedDir: dir.path); }); Timer.periodic(const Duration(seconds: 1), (timer) => print("Timer Running From Isolate 2")); }
第一个线程函数,嵌套执行上面的线程函数
('vm:entry-point') void isolate1(String arg) async { await FlutterIsolate.spawn(isolate2, "hello2"); getTemporaryDirectory().then((dir) { print("isolate1 temporary directory: $dir"); }); Timer.periodic(const Duration(seconds: 1), (timer) => print("Timer Running From Isolate 1")); }
执行线程函数,进行控制 暂停、恢复、杀死
ElevatedButton( child: const Text('03 - isolate 嵌套执行'), onPressed: () async { final isolate = await FlutterIsolate.spawn(isolate1, "hello"); // // 5 秒后暂停 // Timer(const Duration(seconds: 5), () { // print("Pausing Isolate 1"); // isolate.pause(); // }); // // 10 秒后恢复 // Timer(const Duration(seconds: 10), () { // print("Resuming Isolate 1"); // isolate.resume(); // }); // // 20 秒后杀死 // Timer(const Duration(seconds: 20), () { // print("Killing Isolate 1"); // isolate.kill(); // }); }, ),
如果一个界面关闭的时候,你需要全部关闭所有线程
ElevatedButton( child: const Text('04 - 杀掉全部'), onPressed: () async { await FlutterIsolate.killAll(); }, ),
https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_isolate
总之,尽管Future在处理异步操作方面是非常有用的工具,但在某些情况下,使用Isolate可以更好地满足特定的需求,例如执行CPU密集型任务、处理大量数据或并行处理多个任务。因此,选择使用Future还是Isolate取决于您的具体需求和场景。
感谢阅读本文
如果我有什么错?请在评论中让我知道。我很乐意改进。
© 猫哥 ducafecat.com
end
Copyright 2023 ducafecat. All rights reserved.
微信: ducafecat, line: ducafecat,京ICP备2021009050号-3