【问题标题】:How to Display list from Firestore in an item builder如何在项目构建器中显示来自 Firestore 的列表
【发布时间】:2019-01-27 06:43:03
【问题描述】:

下面的 getIngredients() 方法从 firestore 返回一个列表。

Future getIngredients() async {
    return Firestore.instance
        .collection('ingredients')
        .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();
  }

现在我想在下面的项目构建器中显示此列表:

 new ListView.builder(
                  itemExtent: 90,
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                      return SingleIngredient(
                        ingredient_name: snapshot.data[index].ingredients,
                      );
                  });

我收到以下错误消息:

_FutureBuilderState#7cbda):I/flutter (12164):类 'QuerySnapshot' 没有实例 getter 'length'。我/颤振(12164): 接收方:“QuerySnapshot”I/flutter 实例(12164):已尝试 调用:长度

这是我的火库的结构。我正在取配料表:

更新 我已经更新了代码,但我只得到了成分列表中的第一项(即洋葱)。我希望 itembuilder 构建列表中的每个项目,因为我正在尝试显示图像和成分列表。这就是 SingleIngredient 小部件正在做的事情。那么,我怎样才能一个一个地遍历每个列表呢?

 Widget build(BuildContext context) {
    return Container(
      child: FutureBuilder(
          future: getIngredients(),
          builder: (context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data.documents.length,
                itemBuilder: (context, index) {
                  DocumentSnapshot user = snapshot.data.documents[index];

                  return SingleIngredient(
                    // Access the fields as defined in FireStore
                    ingredient_name: user.data['ingredients'][index].toString(),
                  );
                },
              );
            } else if (snapshot.connectionState == ConnectionState.done &&
                !snapshot.hasData) {
              // Handle no data
              return Center(
                child: Text("No users found."),
              );
            } else {
              // Still loading
              return CircularProgressIndicator();
            }
          }),
    );
  }
}

【问题讨论】:

  • 您必须使用snapshot.data.documents 来访问查询的文档,因此要获得长度为snapshot.data.documents.length

标签: dart flutter google-cloud-firestore


【解决方案1】:

这是一个使用 StreamBuilder 的示例,我从集合中检索所有文档并构建一个 ListView 来显示它们:

Widget buildUserList(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (snapshot.hasData) {
        return ListView.builder(
            itemCount: snapshot.data.documents.length,
            itemBuilder: (context, index) {
                DocumentSnapshot user = snapshot.data.documents[index];

                return ListTile(
                    // Access the fields as defined in FireStore
                    title: Text(user.data['firstName']),
                    subtitle: Text(user.data['lastName']),
                );
            },
        );
    } else if (snapshot.connectionState == ConnectionState.done && !snapshot.hasData {
        // Handle no data
        return Center(
            child: Text("No users found."),
        );
    } else {
        // Still loading
        return CircularProgressIndicator();
    }
}

用法:

Scaffold(
    body: StreamBuilder(
        stream:
            Firestore.instance.collection('users').snapshots(),
        builder: buildUserList,
    )
)

Scaffold(
    body: FutureBuilder(
        future:
            Firestore.instance.collection('users').getDocuments(),
        builder: buildUserList,
    )
)

【讨论】:

  • 您提供的示例将打印单值字段。我想打印和存储一个数组字段。我该怎么做?
  • 您可以从构建器返回任何小部件以显示您想要的任何类型的数据。它不一定是ListViewDocumentSnapshot.data 中的所有字段都是 dynamic,因此您可以执行类似 List&lt;String&gt; list = snapshot.data.documents[index].data['myListKey']; 的操作来检索值。
  • 两者都会起作用。如果你想使用getDocuments(),你需要一个FutureBuilder,因为它返回一个Future&lt;QuerySnapshot&gt;。这里调用snapshots() 使其返回Stream&lt;QuerySnapshot&gt;
  • 没错,我正在使用 FututeBuilder,但是如何在不使用 streambuilder 的情况下显示结果?您能否提供一个从 Firestore 访问数组字段的示例?
  • 它们的使用方式基本相同。更新答案
【解决方案2】:

Dart 不知道你从 Future 返回什么类型,所以它将它解释为一个动态对象,它没有长度获取器。改变你的方法

Future getIngredients() async {
return Firestore.instance
    .collection('ingredients')
    .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();

}

收件人

Future<List<YourType>> getIngredients() async {
return Firestore.instance
    .collection('ingredients')
    .where("name", isEqualTo: widget.dish_name.toString().toLowerCase()).getDocuments();

}

YourType 是从 getDocuments() 函数返回的类型。您可能还需要对其执行 toList()。

【讨论】:

  • 我在实现您的更改时收到以下错误:返回类型 'Future 不是方法 getIngredients 定义的 'Future>'
  • @bangbang 你在返回一个 List getDocuments 返回什么?
  • 请看附件的firestore文档结构。我正在返回一份成分列表(字符串)。
  • 如果我将查询更改为以下内容: Future getIngredients() async { return Firestore.instance .collection('ingredients') .where("name", isEqualTo: widget.dish_name.toString( ).toLowerCase()).snapshots() .listen((data) => data.documents.forEach((doc) => print(doc["ingredients"])));我能够得到一份成分清单。我只是不知道如何在小部件中显示它
【解决方案3】:
body: StreamBuilder(
stream: Firestore.instance
    .collection('ups')
.where('pc',
isEqualTo: widget.post.data["pc"])
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: Text("Loading..."),
);
} else {
final ups = snapshot.data.documents;
List<String> stateWidget = [];
for (var message in ups) {
final stateText = message.data['state'];
// final stateCollection = Text('$stateText');
stateWidget.add(stateText);
}enter code here
return  ListView(
children: stateWidget
    .map((data) => ListTile(`enter code here`
title: Text(data),
onTap: () => {_selectedItem(data)}))
    .toList(),`enter code here`
)

【讨论】:

  • 嗨@miriam,您可以缩进代码以使其更具可读性。一些右大括号似乎丢失了,enter code here 字符串似乎错误。
猜你喜欢
  • 2022-12-09
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2018-11-22
相关资源
最近更新 更多