在 Flutter 中,如果你想让 FutureBuilder
的 future
函数再次执行,可以通过以下几种方式实现:
方法 1:使用 Key
强制重建 FutureBuilder
通过改变 FutureBuilder
的 key
,可以强制 Flutter 重建它,从而重新执行 future
函数:
class MyWidget extends StatefulWidget {
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// 使用 UniqueKey 来强制重建 FutureBuilder
UniqueKey _futureBuilderKey = UniqueKey();
Future<String> fetchData() async {
// 模拟网络请求
await Future.delayed(Duration(seconds: 2));
return "New Data: ${DateTime.now()}";
}
void _refreshData() {
setState(() {
// 改变 key,FutureBuilder 会重新执行 future
_futureBuilderKey = UniqueKey();
});
}
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _refreshData,
child: Text("Refresh Data"),
),
FutureBuilder<String>(
key: _futureBuilderKey, // 关键点:改变 key 会重建 FutureBuilder
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Error: ${snapshot.error}");
}
return Text("Data: ${snapshot.data}");
},
),
],
);
}
}
方法 2:使用 StatefulWidget
管理 future
在 StatefulWidget
中存储 future
,并在需要刷新时重新调用 fetchData
:
class MyWidget extends StatefulWidget {
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future<String>? _futureData;
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return "New Data: ${DateTime.now()}";
}
void initState() {
super.initState();
_futureData = fetchData(); // 初始化 future
}
void _refreshData() {
setState(() {
_futureData = fetchData(); // 重新赋值 future
});
}
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _refreshData,
child: Text("Refresh Data"),
),
FutureBuilder<String>(
future: _futureData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Error: ${snapshot.error}");
}
return Text("Data: ${snapshot.data}");
},
),
],
);
}
}
方法 3:使用 StreamBuilder
替代 FutureBuilder
如果数据需要频繁刷新,可以考虑使用 Stream
+ StreamBuilder
:
class MyWidget extends StatefulWidget {
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final StreamController<String> _streamController = StreamController();
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return "New Data: ${DateTime.now()}";
}
void _refreshData() {
fetchData().then((data) {
_streamController.add(data); // 手动推送新数据到 Stream
});
}
void initState() {
super.initState();
_refreshData(); // 初始化数据
}
void dispose() {
_streamController.close();
super.dispose();
}
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _refreshData,
child: Text("Refresh Data"),
),
StreamBuilder<String>(
stream: _streamController.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Error: ${snapshot.error}");
}
return Text("Data: ${snapshot.data}");
},
),
],
);
}
}
总结
方法 | 适用场景 | 特点 |
---|---|---|
改变 Key |
简单场景 | 强制重建 FutureBuilder ,适合一次性刷新 |
重新赋值 future |
推荐方式 | 通过 setState 更新 future ,逻辑清晰 |
StreamBuilder |
频繁刷新 | 适合需要持续监听数据变化的场景 |
选择最适合你需求的方式即可!