gpt4 book ai didi

dart - FutureBuilder 与 setState 的结合使用

转载 作者:IT王子 更新时间:2023-10-29 06:36:08 28 4
gpt4 key购买 nike

如何正确使用FutureBuildersetState?例如,当我创建一个有状态小部件时,它开始加载数据 (FutureBuilder),然后我应该用新数据更新列表,所以我使用 setState,但它开始无限循环(因为我再次重建小部件),任何解决方案?

class FeedListState extends State<FeedList> {

Future<Null> updateList() async {
await widget.feeds.update();
setState(() {
widget.items = widget.feeds.getList();
});
//widget.items = widget.feeds.getList();
}

@override
Widget build(BuildContext context) {
return new FutureBuilder<Null>(
future: updateList(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Center(
child: new CircularProgressIndicator(),
);
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return new Scrollbar(
child: new RefreshIndicator(
child: ListView.builder(
physics:
const AlwaysScrollableScrollPhysics(), //Even if zero elements to update scroll
itemCount: widget.items.length,
itemBuilder: (context, index) {
return FeedListItem(widget.items[index]);
},
),
onRefresh: updateList,
),
);
}
},
);
}
}

最佳答案

事实上,它会无限循环,因为每当 build 被调用时,updateList 也会被调用并返回一个全新的 future。

您必须保持您的build 纯净。它应该只读取和组合变量和属性,但绝不会产生任何副作用!


另一个注意事项:您的 StatefulWidget 子类的所有字段都必须是最终的(widget.items = ... 是错误的)。更改的状态必须存储在 State 对象中。

在这种情况下,您可以将结果(列表的数据)存储在未来本身中,不需要单独的字段。从 future 调用 setState 甚至是危险的,因为 future 可能会在处理状态后完成,并且会抛出错误。

这里是一些更新代码,考虑了所有这些事情:

class FeedListState extends State<FeedList> {
// no idea how you named your data class...
Future<List<ItemData>> _listFuture;

@override
void initState() {
super.initState();

// initial load
_listFuture = updateAndGetList();
}

void refreshList() {
// reload
setState(() {
_listFuture = updateAndGetList();
});
}

Future<List<ItemData>> updateAndGetList() async {
await widget.feeds.update();

// return the list here
return widget.feeds.getList();
}

@override
Widget build(BuildContext context) {
return new FutureBuilder<List<ItemData>>(
future: _listFuture,
builder: (BuildContext context, AsyncSnapshot<List<ItemData>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return new Center(
child: new CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return new Text('Error: ${snapshot.error}');
} else {
final items = snapshot.data ?? <ItemData>[]; // handle the case that data is null

return new Scrollbar(
child: new RefreshIndicator(
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(), //Even if zero elements to update scroll
itemCount: items.length,
itemBuilder: (context, index) {
return FeedListItem(items[index]);
},
),
onRefresh: refreshList,
),
);
}
},
);
}
}

关于dart - FutureBuilder 与 setState 的结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52021205/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com