在 Firestore 查询中 Flutter 传递文档 ID

Posted

技术标签:

【中文标题】在 Firestore 查询中 Flutter 传递文档 ID【英文标题】:Flutter Passing Document ID in Firestore Query 【发布时间】:2020-03-16 17:25:38 【问题描述】:

我正在想办法做到这一点。

如果我通过硬编码的文档 ID,它就可以工作。但是由于我有多个页面,所以我想弄清楚如何传递它然后查询它..

我的主页有以下内容。

import 'package:flutter/material.dart';
import 'package:onlytag2/pages/category.dart';
import 'package:onlytag2/widget/maincard.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';

class Home extends StatefulWidget 
  @override
  _HomeState createState() => _HomeState();


class _HomeState extends State<Home> 
  StreamSubscription<QuerySnapshot> subscription;

  List<DocumentSnapshot> snapshot;

  Query collectionReference = Firestore.instance.collection("mainCategories").orderBy("title");

  void initState() 
    subscription = collectionReference.snapshots().listen((datasnapshot) 
      setState(() 
        snapshot = datasnapshot.documents;
      );
    );
    super.initState();
  

  @override
  void dispose() 
    subscription.cancel(); //Streams must be closed when not needed
    super.dispose();
  

  passData(DocumentSnapshot snap, String cat, String title) 
    print(cat);
    Navigator.of(context).push(
        MaterialPageRoute(builder: (context) => Category(snapshot: snap, category: cat, title: title,)));
  

  @override
  Widget build(BuildContext context) 
    if (snapshot == null) return Center(
      child: Container(
        color: Colors.black,
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.black,
          constraints: BoxConstraints(
              maxHeight: 300.0,
              maxWidth: 200.0,
              minWidth: 150.0,
              minHeight: 150.0
          ),
          child: CircularProgressIndicator(),
        ),
      ),
    );
    return Scaffold(
      backgroundColor: Color(0xff0E0E0F),
      appBar: AppBar(
        centerTitle: true,
        backgroundColor: Colors.black,
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              "#",
              style: TextStyle(
                  fontSize: 25, color: Color(0xffff9900), fontFamily: 'Dokyo'),
            ),
            Text(
              "onlytags",
              style: TextStyle(color: Colors.white, fontFamily: 'Dokyo'),
            )
          ],
        ),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Column(
              children: <Widget>[
                Expanded(
                  child: ListView.builder(
                      itemCount: snapshot.length,
                      itemBuilder: (context, index) 
                        return InkWell(
                          onTap: () => passData(snapshot[index], snapshot[index].documentID.toString(), snapshot[index].data["title"] ),
                          child: MainCard(
                            title: snapshot[index].data["title"],
                            subtitle: snapshot[index].data["subTitle"],
                            image: snapshot[index].data["image"],
                          ),
                        );
                      ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  

类别小部件是我遇到问题的地方。

评论列出了我遇到问题的地方。

import 'package:flutter/material.dart';
import 'package:onlytag2/widget/sub.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';

class Category extends StatefulWidget 
  DocumentSnapshot snapshot;
  final String category;
  final String title;

  Category(this.snapshot, this.category, this.title);

  @override
  _CategoryState createState() => _CategoryState();


class _CategoryState extends State<Category>
  StreamSubscription<QuerySnapshot> subscription;

  List<DocumentSnapshot> snapshot;

  //How do I get the category passed properly? I know it is the Document ID, but since it changes based on what button is pressed before,
  //I cant figure out how to pass it..
  Query collectionReference = Firestore.instance.collection("mainCategories").document(widget.category).collection("subCategories").orderBy("title");

  void initState() 
    subscription = collectionReference.snapshots().listen((datasnapshot) 
      setState(() 
        snapshot = datasnapshot.documents;
      );
    );
    super.initState();
  


  @override
  void dispose() 
    subscription.cancel(); //Streams must be closed when not needed
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    if (snapshot == null) return Center(
      child: Container(
        color: Colors.black,
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.black,
          constraints: BoxConstraints(
              maxHeight: 300.0,
              maxWidth: 200.0,
              minWidth: 150.0,
              minHeight: 150.0
          ),
          child: CircularProgressIndicator(),
        ),
      ),
    );
    return Scaffold(
      backgroundColor: Color(0xff0E0E0F),
      appBar: AppBar(
        iconTheme: IconThemeData(
          color: Color(0xffff9900),
        ),
        centerTitle: true,
        backgroundColor: Colors.black,
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text(
              "#", style: TextStyle(fontSize: 25, color: Color(0xffff9900), fontFamily: 'Dokyo'),
            ),
            Text(widget.title.toLowerCase(), style: TextStyle(color: Colors.white, fontFamily: 'Dokyo'),)
          ],
        ),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Column(
              children: <Widget>[
                Expanded(
                  child: ListView.builder(
                      itemCount: snapshot.length,
                      itemBuilder: (context, index) 
                        return Sub(
                          title: snapshot[index].data["title"],
                          subtitle: snapshot[index].data["subTitle"],
                          image: snapshot[index].data["image"],
                        );
                      ),
                ),
                Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 15),)
              ],
            ),
          ),
        ],
      ),
    );
  

【问题讨论】:

I am trying to figure out how to pass it and then query it 是什么意思。我认为在上面的代码中,文档 ID 被传递给 _CategoryState,这是什么意思? 所以现在我有子类别。我需要列表生成器来为该文档 ID 构建这些子类别。 widget.category 不起作用。它给了我一个错误 具体会抛出什么错误? widget.category 在查询中抛出错误 only static members can be access in intializers 【参考方案1】:

我已经意识到评论中的代码看起来很可疑,所以让我来回答一下。 Flutter 目前不支持您尝试执行的操作,这可以在这些 GitHub 问题 1 和 2 中看到。

将您的代码更改为,

class _CategoryState extends State<Category>
  StreamSubscription<QuerySnapshot> subscription;

  List<DocumentSnapshot> snapshot;

  Query collectionReference;

  void initState() 
    collectionReference = Firestore.instance.collection("mainCategories").document(widget.category).collection("subCategories").orderBy("title");
    subscription = collectionReference.snapshots().listen((datasnapshot) 
      setState(() 
        snapshot = datasnapshot.documents;
      );
    );
    super.initState();
  

...

希望这会有所帮助。

【讨论】:

完美运行!谢谢!足够简单的修复。

以上是关于在 Firestore 查询中 Flutter 传递文档 ID的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Firestore 复合查询

在 Firestore 查询中 Flutter 传递文档 ID

Flutter:按时间戳查询 Firestore 文档

查询时如何在 Flutter (Dart) 中使用变量 Cloud Firestore

如何使用 Firestore 在 Flutter 中搜索文本

Flutter Firestore 地理查询