【问题标题】:List.contains() not working on a list of firestore documentsnapshotsList.contains() 不适用于 Firestore 文档快照列表
【发布时间】:2020-03-24 17:42:40
【问题描述】:

我有一个包含多个文档快照的列表。当我执行 list.contains(documentsnapshot) 时,它总是返回 false。示例:

DocumentSnapshot a = document;
List<DocumentSnapshot> snapshots = []
snapshots.add(a);

snapshots.contains(a) // false

实际代码的精简版

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class AddUsersDialog extends StatefulWidget {

  @override
  _AddUsersDialogState createState() => _AddUsersDialogState();
}

class _AddUsersDialogState extends State<AddUsersDialog> {

  List<DocumentSnapshot> selected = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Container(
        child: Column(
          children: <Widget>[
            // row to display the selected users
            Row(
              children: List.generate(selected.length,
                (index) => InkWell(
                   onTap: () => setState(() => selected.removeAt(index)),
                   child: Text(selected[index]['name']),
                 );
              ),
            ),
            // list of all users
            StreamBuilder<QuerySnapshot>(
                stream: getUsers(),
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> snapshot) {
                  if (snapshot.hasData) {
                    List<DocumentSnapshot> users = snapshot.data.documents;
                    return Flexible(
                      child: ListView.builder(
                        itemCount: users.length,
                        itemBuilder: (BuildContext context, int index) {
                          return ListTile(
                            leading: Text(users[index]['name']),
                            onTap: () => setState(() {
                              if (selected.contains(users[index])) return;
                              selected.add(users[index]);
                            }),
                          );
                        },
                      ),
                    );
                  } 
                }
             ),
          ],
        ),
      ),
    );
  }
} 

我得到了流生成器数据,它显示得很好,我可以将 documentSnapshots 添加到所选列表中,并且可以再次删除它们。只有当我签入用户列表时,如果用户已经在选定的列表中,它总是会返回 false,即使当我打印列表和用户时,我可以看到它在那里。

解决方案 显然,直接比较 DocumentSnapshots 会给出 Morez 回答中描述的问题。我通过创建自定义包含函数来解决它

bool contains(List<DocumentSnapshot> list, DocumentSnapshot item) {
    for (DocumentSnapshot i in list) {
      if (i.documentID == item.documentID) return true;
    }
    return false;
  }

【问题讨论】:

    标签: firebase flutter arraylist dart google-cloud-firestore


    【解决方案1】:

    我刚刚运行了一个类似的代码,但它按预期工作。确保您的文档不为空,因为这可能是问题所在。但是如果你成功添加文档,你会得到 snapshots.contains(a) 为真。

    更新答案

    我认为问题在于您正在比较对象。当您第二次运行 if 语句时,您会比较具有相同详细信息的两个不同对象,因为每次运行构建器时,您都会在内存中创建一个新对象。因此,正在比较 2 个不同的内存位置,结果始终为 false,因此您始终将对象添加到列表中。您可以使用identical(this,other) 或查看它们的哈希码以了解它们是不同的对象。

    解决方案是检查对象的独特之处并进行比较。您可以检查他们的 id 或他们的姓名,如果他们不同,则用户不同,然后您将其添加到您的列表中。

    你也可以看看this

    【讨论】:

    • 好吧,但是,1. 项目不在列表中 2. if 语句返回 false 3. 将项目添加到列表 4. 第二次按下项目 5. 项目已经添加到列表中,所以if 语句返回 true,因此不会再次添加项目。
    • 我可以打印列表并看到每次我单击一个项目时它都会添加到该列表中
    • 所以当你打印列表时,你有 2 个相同的对象?还是最后只有一个?
    • 当我打印列表时,我有两个相同的对象,即使我在添加另一个之前检查了列表是否包含该项目。
    • 我认为问题在于您正在比较对象。当您第二次运行 if 语句时,您会比较具有相同详细信息的两个不同对象,因为每次运行构建器时,您都会在内存中创建一个新对象。因此,正在比较 2 个不同的内存位置,结果始终为 false,因此您始终将对象添加到列表中。看看stackoverflow.com/questions/16069106/…
    猜你喜欢
    • 2021-12-06
    • 2022-01-25
    • 2021-09-27
    • 2020-12-16
    • 2018-03-19
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    相关资源
    最近更新 更多