setState对FutureBuilder的使用
如何使用FutureBuilder
与setState
正常吗?例如,当我创建一个有状态的小部件时,它开始加载数据(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
也被调用并返回全新的未来。
你必须保持build
纯洁。它应该只读取并组合变量和属性,但绝不会引起任何副作用!
另一个注意事项:StatefulWidget
子类的所有字段都必须为final(widget.items =
...不好)。更改的状态必须存储在State
对象中。
在这种情况下,您可以将结果(列表中的数据)存储在将来的本身中,而无需单独的字段。setState
从将来调用它甚至很危险,因为将来可能会在处置状态之后完成,并且会引发错误。
这是一些考虑了所有这些因素的更新代码:
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,
),
);
}
},
);
}
}
以上是 setState对FutureBuilder的使用 的全部内容, 来源链接: utcz.com/qa/399148.html