【问题标题】:FutureBuilder not refreshing with new dataFutureBuilder 不刷新新数据
【发布时间】:2021-05-12 16:21:37
【问题描述】:

我有一个 TabFolder。在我的选项卡中,我有一个带有许多按钮的 ListView。这些按钮是通过引用 JSON 文件中的项目创建的,这意味着我必须使用 Future 来获取 JSON,并使用 FutureBuilder 来构建我的列表。所有这些都运行良好。

现在,当我长按此列表中的某个项目时,我会弹出一个警报,要求用户确认或取消操作。操作是删除。确认后,删除操作会从 JSON 文件中删除按钮项。这工作得很好。

我现在正在尝试重建列表,并删除了该项目,但无论我尝试了什么,它都停留在那里,直到我移动到另一个选项卡并再次返回(我必须重复两次)。

如何让我的 FutureBuilder 刷新对 JSON 的调用。我已经尝试进行另一个调用以从警报返回中获取我的 Future (JSON),我已经在我的 FutureBuilder 中尝试过,我已经在 onLongPress 中尝试过,我已经尝试在很多地方放置 setState...

当您知道它应该工作时,这种异步令人沮丧(如果我不必使用异步和 Futures 它将工作)。 无论如何,这是我的 FutureBuilder 代码。

  Widget buildInProgress(List<Widget> inProgressList) {
    return Center(
      child: FutureBuilder<InProgressList>(
        future: futureInProgressList,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            inProgressList.clear();
            snapshot.data!.Forms!.forEach((InProgressItems formItem) {
              inProgressList.add(
                Container(
                  child: TextButton(
                    child: Row(
                      children: [
                        RichText(text: TextSpan(
                            text: formItem.formName! + "\n",
                            style: TextStyle(color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.bold,),
                            children: <TextSpan>[
                              TextSpan(
                                text: formItem.displayDetail!,
                                style: TextStyle(color: Colors.grey[700], fontSize: 11.0,),
                              ),
                            ]
                        )),
                      ],
                    ),
                    onPressed: () {
                      getFormSendData(context, formItem);
                    },
                    onLongPress: () {
                      setState(() {
                        _popupDeleteQuestion(context, formItem);
                      });
                    },
                  ),
                  decoration: BoxDecoration(
                    border: Border(bottom: BorderSide(color: Colors.purple[400]!)),
                  ),
                ),
              );
            });
            return
              ListView(
                children: inProgressList,
                padding: EdgeInsets.all(8.0),
              );
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          }
          // By default, show a loading spinner
          return CircularProgressIndicator();
        },
      ),
    );
  }

我已经为我的 TabController 设置了一个监听器来处理选项卡选择...

  _handleTabSelection() {

    switch(_tabController!.index) {
      case 0:
        setState(() {

        });
        break;
      case 1:
        setState(() {
          futureFormList = fetchForms();
        });
        break;
      case 2:
        setState(() {
          futureInProgressList = showInProgressOrSubmitted("InProgress.json");
        });
        break;
      case 3:
        setState(() {
          futureSubmittedList = showInProgressOrSubmitted("Submitted.json");
        });
        break;
    }

  }

监听器命中,BuildInProgress 命中,但页面没有用新数据刷新。

非常感谢您的帮助。

  void _popupDeleteQuestion(BuildContext context, InProgressOrSubmittedItems formItem) async {

    showDialog(
        context: context,
        builder: (context)
        {
          return AlertDialog(
            title:Text("DELETE FORM"),
            content: StatefulBuilder(
                builder: (context, setState) {

                  return Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[

                      Text("Warning: This will delete all the data contained in this form.")

                    ],
                  );
                }),

            actions: <Widget>[
              new TextButton(
                onPressed: () {
                  setState((){

                  });
                  Navigator.of(context).pop();
                },
                //Color: Theme.of(context).primaryColor,
                child:  Text('Cancel'),
              ),
              new TextButton(
                onPressed: () async {
                  _deleteForm(formItem);
                  setState((){
                  Navigator.of(context).pop();
                  });

                },
                child:  Text('Accept'),
              ),
            ],
          );
        });

  }

  void _deleteForm(InProgressOrSubmittedItems formItem) async {
    HandleFile file = new HandleFile();

    file.deleteFile("${formItem.documentId}*");

    String detailFile = await file.readFile("InProgress.json");

    Map<String, dynamic> formData = new Map<String, dynamic>();

    if (detailFile != "")
    {
      formData = jsonDecode(detailFile);
    }

    List<dynamic> ipforms = [];

    if (formData.isNotEmpty)
    {
      ipforms = formData["FileList"];
    }

    List<dynamic> formDetail = [];
    try {
      formDetail = ipforms.where((element) => element["documentId"] !=
          formItem.documentId).toList();
    }
    catch (e) {

    }

    formData["FileList"] = formDetail;

    file.writeFile("InProgress.json", json.encode(formData));
  }

}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    你应该在删除方法之后添加setState。如果你的删除方法返回Future,请在方法前面添加await

     _popupDeleteQuestion(context, formItem);
     setState(() {});
    

    编辑

    _popupDeleteQuestion 方法中,您实际上不需要添加setState。在前面添加await

    onPressed: () async {
          await _deleteForm(formItem);
          Navigator.of(context).pop();
    },
    

    调用_popupDeleteQuestion方法后,调用setState重建。

     _popupDeleteQuestion(context, formItem).then((onValue){
          setState(() {});
    });
        
    

    【讨论】:

    • 感谢您的快速回复。我已经编辑并放置了一个 await 所以现在它看起来 await _popupDeleteQuestion(context, formItem);但是,我有一个红色标记,表示它只能放在异步函数中。如果我将 buildInProgress 设为异步,它会告诉我 Widget 需要成为 Future。
    • 让我澄清一下...我的 _popupDeleteQuestion 返回一个 void,但它是一个异步方法。该选项卡仍显示更改了我的 onLongPress 的旧数据(并且我还更改了我的 _handleTabSelection。它似乎仍然不起作用。
    • 删除代码添加。 onLongPress是弹出一个alert对话框,当点击Accept时,调用delete。
    • 感谢您继续进行此操作。为了使这些工作(我在 _deleteForm 和 _popupDeleteQuestion 上都有红线),我必须在 _popupDeleteQuestion 和 _deleteForm 函数中添加“Future”。它仍然没有工作。然后我使onLongPress异步并等待_popupDeleteQuestion,它也不起作用。
    • 当我第一次启动应用程序时,我的标签文件夹会调用 showInProgressOrSubmitted。当我单击选项卡时,它会再次调用。当我长按行时,它会再次调用。当我在删除上单击接受时,它会调用 _deleteForm。它不会重新调用 showInProgressOrSubmitted。当我更改选项卡(并再次返回)时,它调用 showInProgressOrSubmitted 两次,但屏幕没有更新以显示它已被删除。 (我还是 Flutter 的新手)
    【解决方案2】:

    经过一段时间的尝试解决这个问题,我现在可以正常工作了。在@John Joe 的帮助和更多的谷歌搜索下,我完全改变了方法。我现在直接使用 ListView.builder 来代替循环并将项目添加到列表中。结合 John 的建议,我认为 ListView.builder 是关键。

      Widget buildInProgressList() {
        return Center(
          child: FutureBuilder<InProgressOrSubmittedList>(
              future: futureInProgressList,
              builder: (context, snapshot) {
                  if (snapshot.hasData) {
                  return ListView.builder(
                      itemCount: snapshot.data!.pForms!.length,
                      itemBuilder: (context, index) {
                        InProgressOrSubmittedItems formItem = snapshot.data!
                            .pForms![index];
                        return Container(
                          child: TextButton(
                            child: Row(
    
                              children: [
                                RichText(text: TextSpan(
                                    text: formItem.formName! + "\n",
                                    style: TextStyle(color: Colors.black,
                                      fontSize: 15.0,
                                      fontWeight: FontWeight.bold,),
                                    children: <TextSpan>[
                                      TextSpan(
                                        text: formItem.displayDetail!,
                                        style: TextStyle(
                                          color: Colors.grey[700], fontSize: 11.0,),
    
                                      ),
                                      TextSpan(
                                        text: "\nLast Updated: ${formatDate(
                                            formItem.lastUpdated!)}",
                                        style: TextStyle(
                                          color: Colors.grey[700], fontSize: 11.0,),
    
                                      ),
                                    ]
                                )),
                              ],
                            ),
    
                            onPressed: () async {
                              await getFormSendData(context, formItem).then((
                                  onValue) {
                                setState(() {});
                                futureInProgressList =
                                    showInProgressOrSubmitted("InProgress.json");
                              });
                            },
                            onLongPress: () async {
                              await _popupDeleteQuestion(context, formItem).then((
                                  onValue) {
                                setState(() {});
                                futureInProgressList =
                                    showInProgressOrSubmitted("InProgress.json");
                              });
                              //futureInProgressList = showInProgressOrSubmitted("InProgress.json");
    
                            },
    
                          ),
                          decoration: BoxDecoration(
                            //color: Colors.purple[400],
                            border: Border(
                                bottom: BorderSide(color: Colors.purple[400]!)),
                          ),
                        );
                      }
                  );
                }
                else
                  {
                    return Container();
                  }
              }
          ),
        );
      }
    

    我还必须对删除的处理方式进行一些更改。在我的 AlertDialog 上的 Accept 按钮的 onPressed 中,我也做了类似于 John 提到的解决方案。

    onPressed: () async {
       await _deleteForm(formItem).then((value) {
           Navigator.of(context).pop();
           setState(() {});
           futureInProgressList = showInProgressOrSubmitted("InProgress.json");
       });
    },
    

    我必须将我的 _deleteForm 函数设置为 Future,这样我才能得到“.then”。

    希望这可以帮助其他有类似问题的人。

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 1970-01-01
      • 2021-05-04
      • 2021-04-19
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 2020-05-24
      相关资源
      最近更新 更多