Flutter隔离通信插件isolate_rpc的使用
Flutter隔离通信插件isolate_rpc的使用
isolate_rpc
让 Isolate
的使用变得更加愉快。这是一个为 Isolate
设计的简单的RPC风格API。
特性
isolate_rpc
提供了一种更简单的方法来将非UI任务转移到隔离(Isolate),并且可以作为 Isolate.run
(在 Flutter 中为 compute
)的替代方案,并且性能更好,适用于 Dart SDK < 2.19.0。
该库显著减少了 Isolate.run
的开销。Isolate.run
每次调用都会创建新的隔离(Isolate)。在我的 M1 Pro MacBook 上进行基准测试,每个隔离启动的开销大约为 85 微秒。我相信在低端移动设备上这个数字会更大。
想象一下,如果你频繁地基于UI交互执行异步的后台操作,例如发送分析数据、获取远程API等,你可能希望消除这种开销。
查看基准结果
平台 | 支持情况 |
---|---|
Flutter | ✅ |
Dart | ✅ |
Web | fallback to use main thread |
入门
步骤1:创建一个单个的RPC服务
import 'package:isolate_rpc/isolate_rpc.dart';
// 定义一个单个的RPC服务,即一个Isolate
IsolateRpc<int, int> rpc = IsolateRpc.single(
processor: (data) => data + 1, // 执行逻辑,即加一操作
debugName: "rpc" // 这将用于作为Isolate的名字
);
步骤2:执行请求并接收响应
// 在隔离中执行正常的Rpc请求
IsolateRpcResponse<int> resp = await rpc.execute(1);
print(resp.result); // 输出: 2
步骤3:关闭RPC服务
rpc.shutdown(); // 关闭接收端口和底层的Isolate。
高级用法
自定义请求和响应类型
class FooRequest {
final String? someString;
FooRequest([this.someString]);
}
class FooResponse {
final int? someInt;
FooResponse([this.someInt]);
}
IsolateRpc<FooRequest, FooResponse> rpc = IsolateRpc.single(
processor: (fooRequest) {
var str = fooRequest.someString;
if (str == null) {
throw ArgumentError("someString should not be null");
} else {
return FooResponse(int.parse(str));
}
},
debugName: "rpc"
);
创建一个RPC服务池以提高性能
IsolateRpc<int, int> rpcPool = IsolateRpc.pool(
size: 4, // 调整要启动的Isolate数量
processor: (data) => data + 1,
debugNamePrefix: "rpc-pool" // 内部使用 "rpc-pool-0", "rpc-pool-1", "rpc-pool-2", "rpc-pool-3"
);
使用 package:logging
日志记录器
import 'package:logging/logging.dart';
void main() {
Logger.root.level = Level.FINEST;
// 日志模式示例,用于与Isolate一起记录日志
log.onRecord.listen((record) {
print('${Isolate.current.debugName}: ${record.level.name}: ${record.time}: ${record.message}');
});
// 接收来自Rpc服务的所有日志
var rpc = IsolateRpc.single(
processor: (data) => data + 1,
debugName: "rpc",
logger: Logger("rpc_logger")
);
}
获取更多详细信息,可以将Rpc服务转换为其基础类实例
var rpc = IsolateRpc.single(
processor: (data) => data + 1,
debugName: "rpc"
) as IsolateRpcService<int, int>;
print(rpc.id);
print(rpc.debugName);
var rpcPool = IsolateRpc.pool(
size: 4,
processor: (data) => data + 1,
debugNamePrefix: "rpc-pool"
) as IsolateRpcExecutor<int, int>;
print(rpcPool.id);
print(rpcPool.debugName);
print(rpcPool.size);
性能对比(与 Isolate.run
对比)
查看基准实现
no_compute
: 无工作负载,立即完成compute
: 大型JSON(数组包含300项)序列化和反序列化communication
: 发送长度从0到1GB的数据到Isolate并立即返回主进程
执行脚本
dart compile exe benchmark/main.dart -o ./benchmark/main
./benchmark/main
更多关于Flutter隔离通信插件isolate_rpc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter隔离通信插件isolate_rpc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用isolate_rpc
插件进行隔离通信的代码示例。isolate_rpc
插件允许你在Flutter应用中通过隔离(isolate)执行耗时操作,从而避免阻塞UI线程。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加isolate_rpc
依赖:
dependencies:
flutter:
sdk: flutter
isolate_rpc: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来获取依赖。
2. 创建隔离通信服务
定义一个在隔离中执行的任务。例如,一个计算斐波那契数列的函数:
// lib/fibonacci_service.dart
import 'package:isolate_rpc/isolate_rpc.dart';
class FibonacciService implements RpcService {
Future<int> fibonacci(int n) {
if (n <= 1) return Future.value(n);
return Future.value(fibonacci(n - 1) + fibonacci(n - 2));
}
@override
RpcMethods getRpcMethods() {
return RpcMethods(
methods: {
'fibonacci': fibonacci,
},
);
}
}
3. 在UI中调用隔离服务
在你的主UI文件中,启动隔离服务并调用它:
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:isolate_rpc/isolate_rpc.dart';
import 'fibonacci_service.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late RpcClient<FibonacciService> _rpcClient;
int? _fibonacciResult;
bool _isCalculating = false;
@override
void initState() {
super.initState();
_startRpcService();
}
void _startRpcService() async {
_rpcClient = await RpcClient.start<FibonacciService>(
isolateBuilder: () => FibonacciService(),
);
}
void _calculateFibonacci(int n) async {
setState(() {
_isCalculating = true;
_fibonacciResult = null;
});
try {
final result = await _rpcClient.call('fibonacci', n);
setState(() {
_fibonacciResult = result;
_isCalculating = false;
});
} catch (e) {
print('Error calculating fibonacci: $e');
setState(() {
_isCalculating = false;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Isolate RPC Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'Enter number',
),
keyboardType: TextInputType.number,
onSubmitted: (value) {
final number = int.tryParse(value) ?? 0;
_calculateFibonacci(number);
},
),
SizedBox(height: 20),
if (_isCalculating)
CircularProgressIndicator()
else if (_fibonacciResult != null)
Text('Fibonacci(${_fibonacciResult!}) = $_fibonacciResult'),
],
),
),
),
);
}
}
4. 运行应用
现在你可以运行你的Flutter应用,并在输入框中输入一个数字来计算斐波那契数列。计算过程将在隔离中执行,因此不会阻塞UI线程。
总结
上述代码展示了如何在Flutter项目中使用isolate_rpc
插件进行隔离通信。通过定义隔离中的服务和在UI中调用它,你可以执行耗时操作而不影响应用的响应性。