使用新查询重新访问时已创建的嵌套 FutureBuilder 快照仍然存在

Posted

技术标签:

【中文标题】使用新查询重新访问时已创建的嵌套 FutureBuilder 快照仍然存在【英文标题】:Nested FutureBuilder's snapshot that already create still there when re-visit with new query 【发布时间】:2020-10-11 14:45:10 【问题描述】:

有材料应用程序查询数据库以显示类别中的项目。

    页面 [类别] - 选择类别 A(传递的参数作为类别 id A) 页面 [Items] - (仅从数据库中查询项目 A)ListView.builder 正确显示类别 A 的项目 然后点击返回 页面 [Category] ​​-> 选择类别 B(传递的参数作为类别 id B) 页面 [Items] ->(仅从数据库中查询到项目 B)ListView.builder 意外显示类别 A 和 B 的项目

注意:我需要调用条件未来函数来显示项目,然后我调用 FutureBuilder 作为 StreamBuilder 的嵌套。在我们需要一个项目类别之前,它工作正常。导致 StreamBuilder 的结果可能会有所不同。然后观察到 FutureBuilder 的快照没有清理好。


Widget _buildBody(BuildContext context) 
  return StreamBuilder<QuerySnapshot>(
   stream: firestoreInstance.collection('items').where("category", isEqualTo: widget.categoryId).snapshots(),  

   builder: (context, snapshot1)      
     if (!snapshot1.hasData) return LinearProgressIndicator();          
     else return _buildList(context, snapshot1.data.documents);
   ,   
 );


Widget _buildList(BuildContext context, List<DocumentSnapshot> docSnapshot) 
 return FutureBuilder <List<ItemsRecord>> (
      future: getDetailsOfEachItem(context, docSnapshot),
      builder: (context, snapshot2) 
         if (snapshot2.hasData == true)  
            return new ListView.builder(
                         itemCount: snapshot2.data.length,
                         itemBuilder: (BuildContext ctxt, int index)
                         
                           return _buildListItem(context, snapshot2.data[index]);
                         
                        );
          
          else
          
             return Container(hieght: 0);
          
       );

通过调试查询(By StreamBuilder)项目的数据库结果是正确的。只有 B 可用。

Debugging result of step above.
snapshot1 => Category A => 15 items
snapshot1=> Category B => 6 items

但是看起来FutureBuilder中的项目A在快照中仍然存在。

Debugging result of step above.
snapshot2 => Category A => 15 items
snapshot2 => Category A & B => 21 items (Unexpected !)

请帮助建议我如何在 FutureBuilder 的快照 2 中删除意外项目 A。

我尝试添加 snapshot2.data.clear();但是当 hasData 不为真时,数据似乎为空,在 ConnectionState 等待时也是如此。

尝试参考snapshot2.requireData而不是snapshot2.data,结果也一样。

【问题讨论】:

请添加更多代码和上下文,我们无法猜测您还做了什么 @AlbertoMiola 添加了多行代码和解释,希望你能理解我的代码和当前的调试结果。 【参考方案1】:

尝试添加forEach手动删除找到的异常:迭代期间并发修改:'_GrowableList'的实例(长度:21)

搜索然后意识到 dart 有一个选项,在交互过程中我们可以标记要删除的项目,然后使用 removeWhere 在批量操作中删除它们。 Ref

这段代码对我来说很好用。

Widget _buildList(BuildContext context, List<DocumentSnapshot> docSnapshot) 
 return FutureBuilder <List<ItemsRecord>> (
      future: getDetailsOfEachItem(context, docSnapshot),
      builder: (context, snapshot2) 
         if (snapshot2.hasData == true)  

            List<ItemsRecord> records = snapshot2.data;
            List toRemove = [];

            records.forEach((record) 
                if (record.category != widget.categoryId)
                
                   toRemove.add(record);
                
            );
            
            records.removeWhere( (e) => toRemove.contains(e));

            return new ListView.builder(
                         itemCount: snapshot2.data.length,
                         itemBuilder: (BuildContext ctxt, int index)
                         
                           return _buildListItem(context, snapshot2.data[index]);
                         
                        );
          
          else
          
             return Container(hieght: 0);
          
       );

感谢 Alberto Miola,我认为他的问题促使我尝试深入研究问题进行解释,这让我简单地找到了答案。实际上,我们应该称之为解决方法。

【讨论】:

以上是关于使用新查询重新访问时已创建的嵌套 FutureBuilder 快照仍然存在的主要内容,如果未能解决你的问题,请参考以下文章

使用 prisma,如何从嵌套写入中访问新创建的记录(先更新,然后在其中创建)

过滤和排序 SQL 查询以重新创建嵌套结构

每天使用新数据刷新/更新/重新查询访问报告

当我的包是嵌套依赖项时,某些文件未安装,即使它们在作为直接依赖项添加时已安装

在每次页面访问或页面重新加载时显示一个新的 GIF

PostgreSQL JDBC - 使用 PreparedStatements 创建表时已存在关系