Flutter:从子StreamBuilder更新有状态窗口小部件

时间:2019-11-22 09:59:13

标签: flutter google-cloud-firestore

我已经编写了一些简化的代码,在这些代码中,我希望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返回按钮更为简单。

解决方案: 而不是通过.then子句(请参见上面的代码)在异步函数中执行setState

2 个答案:

答案 0 :(得分:0)

通常,您不必执行当前操作。您可以返回Text(“ Waiting ...”);立即调用而不调用setState。根据您的情况,这是一个更好的决定。您响应来自流的事件,并且必须根据当前状态返回内容

return StreamBuilder<DocumentSnapshot>(
      stream: Firestore.instance
          .collection('myCollection')
          .document('myDocument')
          .snapshots(),
      builder: (context, orderSnapshot) {
        if (!orderSnapshot.data.exists)
            return Text("Waiting...");
        else return Text(orderSnapshot);
      });

答案 1 :(得分:0)

您可以使更新异步,例如将其放入匿名异步回调(如

)中
() async {
    setState();
}();

OR

您可以避免在特定用例中出现状态,例如:

@override
  Widget build(BuildContext context) {
      return StreamBuilder<DocumentSnapshot>(
        stream: Firestore.instance
          .collection('myCollection')
          .document('myDocument')
          .snapshots(),
        builder: (context, orderSnapshot) {
          if (!orderSnapshot.data.exists) {
            return Text("Waiting...");
          } else {
            return Text(orderSnapshot);
          }
        });
  }