Flutter并发执行插件simple_isolate的使用
Flutter并发执行插件simple_isolate的使用
simple_isolate
是一个简化版的 Dart 隔离(isolate)插件。它提供了基于 Future 的 API,支持返回数据、完成处理以及异常处理等功能。
特性
- 基于 Future 的 API,支持返回数据、完成处理以及异常处理。
- 支持双向通信,可以在隔离(isolate)和外部世界之间发送消息。
使用方法
基本用法
首先,安装并导入此包:
import 'package:simple_isolate/simple_isolate.dart';
使用 SimpleIsolate.spawn<T>(entrypoint, argument)
替代 Isolate.spawn
来运行一个类型为 Future<T> Function(SIContext ctx)
的函数作为隔离入口点。
SIContext
类型可以在许多情况下使用,我们将在下面的例子中详细介绍。SIContext.argument
可以获取传递给入口点函数的参数。- 注意入口点函数返回一个
Future<T>
,你可以在数据可跨隔离边界序列化时返回数据到调用方。 SimpleIsolate.spawn
是对Isolate.spawn
的封装,返回一个Future<SimpleIsolate<T>>
。SimpleIsolate.future
用于等待完成或处理来自入口点函数的异常。SimpleIsolate.core
返回内部的 Dart [Isolate]。
例如,返回一些数据:
var si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
var result = '';
// 使用 `ctx.argument` 获取传递给入口点函数的参数。
var to = ctx.argument as int;
for (var i = 0; i < to; i++) {
result += '<data chunk $i>';
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
);
// 等待隔离函数完成。
// 并打印结果。
print(await si.future);
/**
* <data chunk 0><data chunk 1><data chunk 2>
*/
异常处理
由于它是基于 Future 的 API,你可以简单地在 await
语句中使用 try-catch
块来处理异常:
var si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
await Future<void>.delayed(Duration(milliseconds: 500));
throw Exception('Oops!');
},
3,
);
try {
print(await si.future);
} catch (err) {
print('ERROR: $err');
}
/**
* ERROR: Exception: Oops!
*/
从隔离发送消息
使用 Context.sendMsg
从隔离向外部发送消息。simple_isolate
中的消息定义如下:
class SIMsg {
final String name;
final Map<String, dynamic>? params;
SIMsg(this.name, this.params);
}
要处理从隔离发送的消息,可以使用 SimpleIsolate.spawn
中的 onMsgReceived
参数:
Future<void> sendMessagesFromIsolate() async {
var si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
var result = '';
var to = ctx.argument as int;
for (var i = 0; i < to; i++) {
result += '<data chunk $i>';
ctx.sendMsg(
'got-data', {'index': i, 'currentResult': result});
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
onMsgReceived: (msg) {
switch (msg.name) {
case 'got-data':
{
print('MSG> ${msg.params}');
break;
}
default:
{
print(
'Unsupported message ${msg.name}, something went wrong in your code.');
break;
}
}
},
);
print(await si.future);
/**
* MSG> {index: 0, currentResult: <data chunk 0>}
* MSG> {index: 1, currentResult: <data chunk 0><data chunk 1>}
* MSG> {index: 2, currentResult: <data chunk 0><data chunk 1><data chunk 2>}
* <data chunk 0><data chunk 1><data chunk 2>
*/
}
向隔离发送消息
调用 SimpleIsolate.spawn
并设置 bidirectional: true
以启用双向通信。
要向隔离发送消息,使用 SimpleIsolate.sendMsgToIsolate
。并在隔离内使用 SIContext.onMsgReceivedInIsolate
处理这些消息。
注意,如果你的入口点函数退出得太早,发送到隔离的消息可能不会被处理。消息处理依赖于隔离内的内部事件循环。如果退出得太早,隔离会立即退出而无法处理 onMsgReceivedInIsolate
。在下面的示例中,我们调用了 Future<void>.delayed
来利用与隔离关联的事件循环。
Future<void> sendMessagesToIsolate() async {
// 从类型为 [Future<String>(int)] 的函数创建 [SimpleIsolate]。
var si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
var result = '';
ctx.onMsgReceivedInIsolate = (msg) {
switch (msg.name) {
case 'inject':
{
result += msg.params?['value'] as String;
break;
}
default:
{
print(
'Unsupported message ${msg.name}, something went wrong in your code.');
break;
}
}
};
var to = ctx.argument as int;
for (var i = 0; i < to; i++) {
result += '<data chunk $i>';
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
);
await si
.sendMsgToIsolate('inject', {'value': '<injected!!!>'});
print(await si.future);
/**
* <data chunk 0><injected!!!><data chunk 1><data chunk 2>
*/
}
当隔离被杀死时收到通知
当隔离被杀死时,SimpleIsolate.future
将抛出 SimpleIsolateAbortException
异常。
var si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
var count = ctx.argument as int;
var result = '';
for (var i = 0; i < count; i++) {
var data = '<data chunk $i>';
print('--> Appending data $data');
result += data;
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
4,
);
try {
await Future.wait<String>([
// 等待隔离完成。
si.future,
// 在 1 秒后杀死隔离。
() async {
await Future<void>.delayed(Duration(seconds: 1));
si.core.kill();
return Future.value('');
}(),
]);
} on SimpleIsolateAbortException catch (_) {
print('Isolation killed');
}
完整示例代码
以下是一个完整的示例代码,展示了如何使用 simple_isolate
插件:
import 'package:simple_isolate/simple_isolate.dart';
Future<void> futureCompletion() async {
final si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
final count = ctx.argument as int;
var result = '';
for (var i = 0; i < count; i++) {
result += '<data chunk $i>';
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
);
print(await si.future);
/**
* <data chunk 0><data chunk 1><data chunk 2>
*/
}
Future<void> futureException() async {
final si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
await Future<void>.delayed(Duration(milliseconds: 500));
throw Exception('Oops!');
},
3,
);
try {
print(await si.future);
} catch (err) {
print('ERROR: $err');
}
/**
* ERROR: Exception: Oops!
*/
}
Future<void> sendMessagesFromIsolate() async {
final si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
var result = '';
final to = ctx.argument as int;
for (var i = 0; i < to; i++) {
result += '<data chunk $i>';
ctx.sendMsg(
'got-data', {'index': i, 'currentResult': result});
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
onMsgReceived: (msg) {
switch (msg.name) {
case 'got-data':
{
print('MSG> ${msg.params}');
break;
}
default:
{
print(
'Unsupported message ${msg.name}, something went wrong in your code.');
break;
}
}
},
);
print(await si.future);
/**
* MSG> {index: 0, currentResult: <data chunk 0>}
* MSG> {index: 1, currentResult: <data chunk 0><data chunk 1>}
* MSG> {index: 2, currentResult: <data chunk 0><data chunk 1><data chunk 2>}
* <data chunk 0><data chunk 1><data chunk 2>
*/
}
Future<void> sendMessagesToIsolate() async {
final si = await SimpleIsolate.spawn<String>((SIContext ctx) async {
var result = '';
ctx.onMsgReceivedInIsolate = (msg) {
switch (msg.name) {
case 'inject':
{
result += msg.params?['value'] as String;
break;
}
default:
{
print(
'Unsupported message ${msg.name}, something went wrong in your code.');
break;
}
}
};
final to = ctx.argument as int;
for (var i = 0; i < to; i++) {
result += '<data chunk $i>';
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
}, 3, bidirectional: true);
await si
.sendMsgToIsolate('inject', {'value': '<injected!!!>'});
print(await si.future);
/**
* <data chunk 0><injected!!!><data chunk 1><data chunk 2>
*/
}
Future<void> kill() async {
final si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
final count = ctx.argument as int;
var result = '';
for (var i = 0; i < count; i++) {
final data = '<data chunk $i>';
print('--> Appending data $data');
result += data;
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
4,
);
try {
await Future.wait<String>([
si.future,
() async {
await Future<void>.delayed(Duration(seconds: 1));
si.kill();
return Future.value('');
}(),
]);
} on SimpleIsolateAbortException catch (_) {
print('Isolation killed');
}
}
Future<void> onSpawn() async {
final si = await SimpleIsolate.spawn<String>(
(SIContext ctx) async {
final count = ctx.argument as int;
var result = '';
for (var i = 0; i < count; i++) {
result += '<data chunk $i>';
await Future<void>.delayed(Duration(milliseconds: 500));
}
return result;
},
3,
onSpawn: (dynamic argument) => print('onSpawn called with $argument'),
);
print(await si.future);
/**
* <data chunk 0><data chunk 1><data chunk 2>
*/
}
void main(List<String> args) async {
await futureCompletion();
try {
await futureException();
} catch (err) {
print('Error: $err');
}
await sendMessagesFromIsolate();
await sendMessagesToIsolate();
await kill();
await onSpawn();
}
更多关于Flutter并发执行插件simple_isolate的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter并发执行插件simple_isolate的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,simple_isolate
是一个用于简化并发执行的插件,它允许你在不同的隔离(Isolation)中执行任务,从而提高应用程序的性能。Isolates 是Dart中的并发模型,它们允许代码在独立的线程中运行,从而实现并行处理。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 simple_isolate
的依赖:
dependencies:
flutter:
sdk: flutter
simple_isolate: ^0.1.0
然后运行 flutter pub get
来安装依赖。
2. 使用 simple_isolate
simple_isolate
提供了一个简单的API来在隔离中执行任务。以下是一个基本的使用示例:
import 'package:flutter/material.dart';
import 'package:simple_isolate/simple_isolate.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: IsolateExample(),
);
}
}
class IsolateExample extends StatefulWidget {
[@override](/user/override)
_IsolateExampleState createState() => _IsolateExampleState();
}
class _IsolateExampleState extends State<IsolateExample> {
String _result = 'Waiting for result...';
Future<void> _runTaskInIsolate() async {
// 使用 SimpleIsolate 在隔离中执行任务
final result = await SimpleIsolate.run(_heavyComputation, 10);
setState(() {
_result = 'Result: $result';
});
}
static int _heavyComputation(int value) {
// 模拟一个耗时的计算任务
return value * 2;
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Simple Isolate Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_result),
SizedBox(height: 20),
ElevatedButton(
onPressed: _runTaskInIsolate,
child: Text('Run Task in Isolate'),
),
],
),
),
);
}
}