我有一个自定义的 FLutter 小部件,它接收 future 作为其构造函数的参数,并且内部有
FutureBuilder
。
我想添加在连接错误的情况下重新运行此 future 的功能,但问题是首次使用后 future 已“耗尽”。因此,我需要某种方法来创建作为参数传递的未来的副本,以便每次用户按下“重新加载”按钮时使用
FutureBuilder
内部的副本。
import 'package:flutter/material.dart';
class CustomFutureBuilder<T> extends StatefulWidget {
final Future<T> future;
const CustomFutureBuilder({super.key, required this.future});
@override
State<CustomFutureBuilder<T>> createState() => _CustomFutureBuilderState<T>();
}
class _CustomFutureBuilderState<T> extends State<CustomFutureBuilder<T>> {
late Future<T> _future;
@override
void initState() {
// I need to use initState to initialize _future for the first usage of this widget
_future = widget.future; // ← here I want to create a future clone and use it instead of original
super.initState();
}
@override
void didUpdateWidget(covariant CommonFutureBuilder<T> oldWidget) {
_future = widget.future; // ← and here too
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const LinearProgressIndicator();
}
if (snapshot.hasError) {
debugPrint('Loading error: ${snapshot.error}');
return Column(
children: [
const Text(
'Loading error is occurred. Check the internet connection or try again later.'),
OutlinedButton(
onPressed: () {
setState(() {
// ← and maybe here too, I am not sure
});
},
child: const Text('Reload'),
),
],
);
}
final data = snapshot.data as T;
return …
},
);
}
}
你可以尝试用
StreamBuilder
替换FutureBuilder
,因为Future
无法监听变量变化。这是一次性响应。相反,您需要使用 Stream
进行用户刷新或事件。
这是您案例的代码:
late StreamController<T> _conStream;
@override
void initState() {
_conStream= StreamController<T>();
super.initState();
}
@override
void dispose() async {
_conStream.onCancel;
await _conStream.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _conStream.stream,
...
刷新功能:
_conStream.add(await Future.delayed(Duration(seconds: 5), () => 'Done') // as example);