【问题标题】:Use StreamBuilder to display data for current user (not all users' data) from Firestore使用 StreamBuilder 从 Firestore 显示当前用户的数据(不是所有用户的数据)
【发布时间】:2020-07-13 04:53:03
【问题描述】:

我正在尝试在flutter中使用StreamBuilder返回一个列表,但仅适用于当前登录的用户。当我尝试时

StreamBuilder<QuerySnapshot>(
    stream:  _firestore.collection('meals').where('email', isEqualTo: loggedInUser.email).orderBy('date', descending: true).snapshots(),

我不断收到以下错误:

getter 'email' 在 null 上被调用。

接收者:空

尝试调用:电子邮件

当我取出.where 部分时它工作正常,但它只返回每个用户的所有数据,我只希望它返回链接到该当前用户的数据。

任何想法都会非常有帮助,所以提前谢谢你。

杰森

编辑: 这里有一些更多的代码用于更多的上下文:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart';
import 'package:less_food/utilities/add_edit_meal_log.dart';
import 'package:less_food/utilities/constants.dart';

final _firestore = Firestore.instance;
FirebaseUser loggedInUser;

class MealLog extends StatefulWidget {

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

class _MealLogState extends State<MealLog> {
  final _auth = FirebaseAuth.instance;
  FirebaseUser loggedInUser;

  @override
  void initState() {
    super.initState();

    getCurrentUser();
  }

  void getCurrentUser() async {
    try {
      FirebaseUser user = await _auth.currentUser();
      if (user != null) {
        setState(() {
          loggedInUser = user;
          print('this is:  ${loggedInUser.email}');
        });
      }
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            MealsStream(),
          ],
        ),
      ),
    );
  }
}

class MealsStream extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
    stream:  _firestore.collection('meals').where('email', isEqualTo: loggedInUser.email).orderBy('date', descending: true).snapshots(), 
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.lightBlueAccent,
            ),
          );
        }
        final meals = snapshot.data.documents.reversed;
        List<MealBubble> mealBubbles = [];
        for (var meal in meals) {
          final mealDate = meal.data['date'].toDate();
          print(DateFormat('dd-MM-yyyy').format(mealDate));
          final mealSelection = meal.data['mealSelection'];
          final mealDietChoice = meal.data['dietChoice'];

          final mealBubble = MealBubble(
            date: mealDate,
            selection: mealSelection,
            dietChoice: mealDietChoice,
          );

          mealBubbles.add(mealBubble);
        }
        return Expanded(
          child: ListView(
            reverse: false,
            padding: EdgeInsets.symmetric(vertical: 20.0),
            children: mealBubbles,
          ),
        );
      },
    );
  }
}

class MealBubble extends StatelessWidget {
  MealBubble({this.date, this.selection, this.dietChoice});

  final DateTime date;
  final String selection;
  final String dietChoice;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Container(
        color: Colors.white,
        child: Column(
          children: <Widget>[
            Material(
              borderRadius: BorderRadius.circular(10.0),
              elevation: 5.0,
              color: Colors.lightBlueAccent,
              child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 5.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 13.0),
                      child: Text(
                        '${DateFormat('dd-MM-yyyy').format(date)}',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 15.0,
                        ),
                      ),
                    ),
                    Text(
                      selection,
                      textAlign: TextAlign.start,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 15.0,
                      ),
                    ),
                    SizedBox(
                      width: 2.0,
                    ),
                    Text(
                      dietChoice,
                      textAlign: TextAlign.start,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 15.0,
                      ),
                    ),
                    ButtonTheme(
                      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                      minWidth: 0,
                      child: FlatButton(
                        child: Text(
                          'Edit',
                          style: kMealLogEditButtonTextStyle,
                        ),
                        onPressed: () {
                          showModalBottomSheet(
                            context: context,
                            builder: (context) => AddEditMealLog(),
                            isScrollControlled: true,
                          );
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


【问题讨论】:

  • 您的问题是 loggedInUser 为空,这就是您收到错误的原因。向我们展示更多代码,以便我们找出您的对象为空的原因!
  • 嗨@Morez 谢谢你的评论。我已编辑问题以包含更多代码供您查看。

标签: flutter google-cloud-firestore stream-builder


【解决方案1】:

问题是您的全局变量loggedInUser 从未初始化。尽管如此,您确实在另一个类中初始化了另一个具有完全相同名称的变量,我认为这可能会导致您感到困惑。

如您所见,您声明了两个名为 loggedInUserFirebaseUser 对象,一个具有文件范围(它在文件中全局存在),另一个在类中,因此具有类范围(它只存在于内部那堂课!)。当您在函数_MealLongState.getCurrentUser() 中初始化loggedInUser 时,您使用的是类变量,而不是全局变量。然后,当您从方法MealsStream.build() 访问loggedInUser 时,您将获得尚未初始化的全局变量。

解决方案是从类 _MealLogState 中删除变量 loggedInUser 的声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2018-06-17
    • 2023-01-17
    • 2020-02-21
    • 2021-06-16
    • 2020-08-27
    • 1970-01-01
    相关资源
    最近更新 更多