如何获取Firestore上另一个集合内的集合内的所有文档?

时间:2019-08-28 10:55:30

标签: flutter dart

好吧,我正在尝试构建一个函数,当我单击收藏夹图标时,我正在选择一个地点作为我最喜欢的地点之一。如果我想查看自己喜欢的地方,我只需要转到喜欢的页面即可返回我所有喜欢的地方。我的壁炉上有两个最喜欢的地方。当我尝试获取它们时,什么也不会返回……这就是问题所在。

每个喜欢的文档都包含城市,图像等字段。这是我的数据库:https://i.imgur.com/CmTr4vG.png

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

class Favorites extends StatefulWidget {
  @override
  _FavoritesState createState() => _FavoritesState();
}

class _FavoritesState extends State<Favorites> {
  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;

    dynamic loadFavorites() async{
      final FirebaseUser user = await FirebaseAuth.instance.currentUser();
      final dynamic userUid = user.uid;
      return userUid;
    }

    dynamic document = loadFavorites();

    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Padding(
              padding: EdgeInsets.only(top: 30.0, bottom: 5.0),
              child: Text("Favoritos", 
              style: TextStyle(fontSize: 20),
              textAlign: TextAlign.center, 
              ),
            ),
            Container(
              child: FutureBuilder<QuerySnapshot>(
                future: Firestore.instance.collection("users").document(document.toString()).collection("favorites").getDocuments(),
                builder: (context, snapshot){
                  if(!snapshot.hasData){
                    return Center(child: CircularProgressIndicator());
                  }else{
                    return snapshot.data.documents.isEmpty ? Center(child: Text("Nenhum favorito escolhido.")) : ListView.builder(
                      physics: const NeverScrollableScrollPhysics(),
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemCount: snapshot.data.documents.length,
                      itemBuilder: (context, index){
                        return Container(
                          padding: EdgeInsets.all(10.0),
                          child: buildFavorite(width, height, snapshot.data.documents[index]),
                        );

                      },
                    );
                  }
                },
              ),
            ),

          ],  
        ),
      ),     
    );   
  }
  Widget buildFavorite(double width, double height, DocumentSnapshot document){
    return Container(
      padding: EdgeInsets.all(10.0),
      decoration: BoxDecoration(
        color: Colors.white,
        boxShadow: <BoxShadow>[
          BoxShadow(
            color: Colors.grey,
            offset: Offset(1.0, 1.0),
            blurRadius: 10.0,
          ),
        ],
        borderRadius: BorderRadius.circular(10.0),
      ),
      child: Stack(
        children: <Widget>[
          //Padding(padding: EdgeInsets.only(top: 100),),
          Container(
            margin: EdgeInsets.only(bottom: 20.0, left: 20.0),
            child: Text(document["title"], style: TextStyle(fontSize: 18),),
          ),

          Container(
            width: width * 0.37,
            height: height * 0.18,
            decoration: BoxDecoration(
              shape: BoxShape.rectangle,
              image: DecorationImage(
                fit: BoxFit.fill,
                image: NetworkImage(document["image"]),
              ),
              boxShadow: <BoxShadow>[
                BoxShadow(
                  color: Colors.grey,
                  offset: Offset(1.0, 1.0),
                  blurRadius: 1.0,
                ),
              ],
            ),
            margin: EdgeInsets.only(left: width * 0.60),
          ),
          Row(
            children: <Widget>[
              Container(
                margin: EdgeInsets.only(top: 30.0),
                child: Icon(Icons.location_on, color: Colors.red,),

              ),
              Container(
                margin: EdgeInsets.only(left: 10.0, top: 30.0),
                child: Text(document["text"]),
              ),

            ],
          ),
          Row(
            children: <Widget>[
              Container(
                margin: EdgeInsets.only(top: 60.0),
                child: Icon(Icons.phone, color: Colors.red),

              ),
              Container(
                margin: EdgeInsets.only(left: 10.0, top: 60.0),
                child: Text(document["phone"]),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              Container(
                margin: EdgeInsets.only(top: 90.0),
                child: Icon(Icons.timer, color: Colors.red,),
              ),
              Container(
                margin: EdgeInsets.only(left: 10.0, top: 90.0),
                child: Text(document["time"]),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:2)

您的问题在这里:

future: Firestore.instance.collection("users").document(document.toString()).collection("favorites").getDocuments(),

document.toString()将返回Instance of Future<dynamic>,因为此变量的实际类型是您的loadUser()函数的返回类型,即Future<dynamic>toString()方法对象通常是Instance of CLASS_NAME。通常,我强烈建议您通过始终使用显式类型而不是动态类型来利用dart的类型安全性!使用类型时发生错误,表明您尝试执行的操作不正确,可以更好地帮助您理解期望的值。

您正在尝试检索userUid以在FutureBuilder中使用它,但是很遗憾,此功能必须为async,因为您必须从Firebase上获取它。周围的功能(您的build中的Widget)不是异步的。因此,您无法按预期解析loadUser()函数。要解决此问题,您需要在userUid函数之外提取build和收藏夹检索-让我为您展示一个示例:

Future<QuerySnapshot> getFavoritesFromUser() {
  FirebaseUser user = await FirebaseAuth.instance.currentUser();
  final String userUid = user.uid;

  return Firestore.instance.collection("users").document(userUid).collection("favorites").getDocuments();
}

@override
Widget build(BuildContext context) {
  ...
  Container(
    child: FutureBuilder<QuerySnapshot>(
      future: this.getFavoritesFromUser()
      ...