Flutter:FlatButton不会在onPressed上更改子级

时间:2020-04-18 11:02:07

标签: flutter flutter-layout

我想通过按钮onPressed更改Firestore中的值。我知道可能会有几秒钟的延迟,所以我想在等待时显示一个CircularProgressIndicator小部件。但这是行不通的。

这是我的小部件:

Widget save(String id) {
    return new FutureBuilder(
      future: PostController().isAlreadySaved(id),
      builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
        if (snapshot.hasData) {
          if (snapshot.data) {
            return FlatButton(
              onPressed: () {
                setState(() {
                  isSaveLoading = true;
                });

                PostController().deleteSaved(id);

                setState(() {
                  isSaveLoading = false;
                });
              },
              child: !isSaveLoading
                  ? Icon(
                      MyFlutterApp.star,
                      size: 30,
                      color: Colors.redAccent,
                    )
                  : SizedBox(
                      height: 15,
                      width: 15,
                      child: CircularProgressIndicator(
                        strokeWidth: 1,
                      ),
                    ),
            );
          } else {
            return FlatButton(
              onPressed: () {
                setState(() {
                  isSaveLoading = true;
                });

                PostController().save(context, id);

                setState(() {
                  isSaveLoading = false;
                });
              },
              child: !isSaveLoading
                  ? Icon(
                      MyFlutterApp.star,
                      size: 30,
                      color: Colors.grey,
                    )
                  : SizedBox(
                      height: 15,
                      width: 15,
                      child: CircularProgressIndicator(
                        strokeWidth: 1,
                      ),
                    ),
            );
          }
        } else {
          return Container(
            //color: Colors.white,
            width: Adapt.screenW(),

            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Flexible(
                  child: Shimmer.fromColors(
                    baseColor: Colors.grey[400],
                    highlightColor: Colors.grey[50],
                    enabled: true,
                    child: Row(
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
                          child: new Icon(
                            MyFlutterApp.star,
                            size: 30,
                            color: Colors.white,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );
        }
      },
    );
  }

这是我的isAlreadySaved()函数:

Future<bool> isAlreadySaved(String id) async {
    bool isSaved = false;

    QuerySnapshot snapshot =
        await databaseReference.collection('saved').getDocuments();

    snapshot.documents.forEach((a) async {
      if (a.data['postID'] == id&&
          a.data['saver'] == globals.currentUser.uid) {
        isSaved = true;
      }
    });
    return isSaved;
  }

删除功能实际上是从我在firestore中保存的集合中删除文档,而保存功能会创建一个文档并保存。

提前谢谢!

1 个答案:

答案 0 :(得分:1)

我认为问题是因为您太快地更新了窗口小部件树,或者是通过等待PostController作业完成来使浮动的UI线程被锁定...

在这些行中:

onPressed: () {
 setState(() {
   isSaveLoading = true;
 });

 PostController().deleteSaved(id);

 setState(() {
   isSaveLoading = false;
 });
},

在这里,我看到您要更新按钮的正在加载状态。但是问题在于,当您将isSaveLoading设置为true时,您不会等到PostController().deleteSaved(id)完成之后再将isSaveLoading重置为false

另一方面,如果PostController().deleteSaved()做得很长,由于它不是异步的,它可以锁定UI线程一段时间,因此您将永远看不到循环进度条。

您可以使onPressed回调异步,并等待PostController的工作。

onPressed: () async {
 setState(() {
   isSaveLoading = true;
 });

 // The deleteSaved function have to be async too
 await PostController().deleteSaved(id);

 setState(() {
   isSaveLoading = false;
 });
},

希望这会有所帮助!