在处理flutter的订阅升级时,遇到一个问题:升级需要订阅中的交易详情,但是交易详情必须通过stream才能获取,这就导致不能像调用一个异步接口一样直接获取到需要的数据。通过Deepseek搜索查找到了Completer这个概念,可以将事件流转换成一个Future。
在Flutter/Dart中,Completer是一个用于创建和管理Future的工具。它允许我们产生一个Future,并在稍后的时间完成这个Future(无论是成功还是失败)。这在需要将回调或事件转换为Future的情况下非常有用。
Completer的使用场景
1. 将回调转换为Future:当我们使用一些基于回调的API时,可以使用Completer将其转换为Future,以便使用async/await语法。
2. 在多个事件中等待单个事件:例如,在监听事件流时,我们只关心第一个事件或特定条件的事件,可以使用Completer来返回一个Future。
3. 控制异步操作的完成时机:当我们有多个异步操作,需要等待它们全部完成,或者等待第一个完成时,可以使用Completer。


```
import 'dart:async';
import 'package:flutter/material.dart';
class CompleterPage extends StatefulWidget {
const CompleterPage({super.key});
@override
State<CompleterPage> createState() => _CompleterPageState();
}
class _CompleterPageState extends State<CompleterPage> {
@override
initState() {
super.initState();
loadData();
// delayComplete();
}
Completer<String>? completer = Completer<String>();
Future<String> loadData() async {
completer = Completer<String>();
delayComplete();
return completer!.future;
}
// void delayComplete() {
// Future.delayed(const Duration(seconds: 5), () {
// if (completer != null && !completer!.isCompleted) {
// completer!.complete('Data loaded after 5 seconds!');
// }
// });
// }
void delayComplete() {
const int delaySeconds = 6;
Timer.periodic(const Duration(seconds: 1), (timer) {
if (timer.tick < delaySeconds) {
return;
}
timer.cancel();
if (completer != null && !completer!.isCompleted) {
completer!.complete('Data loaded after $delaySeconds seconds!');
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Completer Demo')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder<String>(
future: loadData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text('Data: ${snapshot.data}');
}
},
),
ElevatedButton(
onPressed: () {
completer?.complete('Hello, Completer!');
// completer = null;
},
child: const Text('Load Data'),
),
],
),
);
}
}
```
Completer的使用场景