【发布时间】:2020-03-18 09:05:18
【问题描述】:
我已经编写了一些简化的代码,我希望 Firestore 数据的条件能够更新父窗口小部件。
我收到错误:在构建期间调用了 setState() 或 markNeedsBuild()。
如何从 StreamBuilder 中更新 myVar 的状态?更新 myVar 后,StreamBuilder 将不会被访问,而只会显示文本 Waiting...。
编辑:我更新了 myVar 以用作 Firestore 的文档 ID。为了澄清,我希望能够从 StreamBuilder 内部更新 StreamBuilder 的文档。换句话说,正如问题所说,从子 StreamBuilder 更新有状态小部件。
class MyWidget extends StatefulWidget {
MyWidget({Key key})
: super(key: key);
@override
_MyWidgetState createState() {
return _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
String myVar = "someID";
@override
Widget build(BuildContext context) {
if (myVar == null) {
// update myVar async, so that StreamBuilder will be re-rendered
asyncFunctUpdate(myVar); // edit: finally got it to work if doing setState from asyncFuncUpdate(myvar).then(()=>setState)
return Text("Waiting...");
}
else
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('myCollection')
.document(myVar)
.snapshots(),
builder: (context, orderSnapshot) {
if (!orderSnapshot.data.exists)
setState(() {
myVar = null;
});
else return Text(orderSnapshot);
});
}
}
解决方法: 在我的情况下,像往常一样从 onPressed 函数返回来自 StreamBuilder 和 setState 的按钮更简单。
解决方案: 而不是从异步函数中执行 setState ,而是在 .then 子句中执行(参见上面的代码)
【问题讨论】:
-
您应该创建一个
async方法并从流生成器中调用它。比如:void setMyVar(String var) async { setState(() { myVar = var})。这应该在构建完成后运行。 -
@danypata 调用一个使用 async 关键字的函数,即使它不需要它也不会改变该函数的执行方式——它仍然会在
build完成之前同步执行.至于实际解决方案,请查看 Artem 的回答。 -
确实使调用异步不起作用。它返回相同的错误。我更新了代码,因为它没有足够清楚地描述我的问题。
标签: flutter google-cloud-firestore