【问题标题】:Getting an error when trying to retrieve data from Firebase FireStore document尝试从 Firebase FireStore 文档中检索数据时出错
【发布时间】:2021-08-09 12:58:50
【问题描述】:

我正在尝试检索用户已注册的所有课程,这些课程存在于文档中的数组中。

users 集合中检索课程 ID 后,我正在尝试从 courses 集合中检索课程详细信息。

但在填充courses 变量之前,会执行coursesCollection 语句并抛出以下错误。

======== Exception caught by widgets library =======================================================
The following assertion was thrown building _BodyBuilder:
'in' filters require a non-empty [List].
'package:cloud_firestore/src/query.dart':
Failed assertion: line 706 pos 11: '(value as List).isNotEmpty'

这是导致错误的代码:

 List courses = [];
  var coursesCollection;

  void fetchCourses() async {
    final loggedInUser = FirebaseAuth.instance.currentUser;
    if (loggedInUser != null) {
      final userCollection = await FirebaseFirestore.instance.collection('users').doc(loggedInUser.uid).get();
      courses = userCollection.get('coursesEnrolled');
    }
  }

  @override
  void initState() {
    fetchCourses();
    coursesCollection = FirebaseFirestore.instance.collection('courses').where('courseID', whereIn: courses);
    super.initState();
  }

  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: coursesCollection.snapshots(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(
              child: CircularProgressIndicator(backgroundColor: kBrandColor),
            );
          }
        }
        final courseListStream = snapshot.data!.docs.map((course) {
          return CourseData.fromDocument(course);
        }).toList();

        List<BadgedCourseCard> courseCards = [];
        for (var course in courseListStream) {
          final courseDocID = course.courseDocID;
          final courseID = course.courseID;
          final courseTitle = course.courseTitle;
          final courseImage = course.courseImage;
          final courseBgColor = hexToColor(course.courseBackgroundColor.toString());
hexToColor(course.courseFgColor.toString());
          final badgedCourseCard = BadgedCourseCard(
            courseTitle: courseTitle.toString(),
            courseTitleTextColor: courseFgColor,
            cardBackgroundColor: courseBgColor,
            courseImage: courseImage.toString(),
            courseCardTapped: () {
              Provider.of<CourseProvider>(context, listen: false).currentCourseDetails(
                currentCourseDocID: courseDocID,
                currentCourseID: courseID,
              );
              Navigator.of(context).push(ScaledAnimationPageRoute(CourseLandingPage(courseID: courseID.toString())));
            },
            courseBookmarkTapped: () => print("Course Bookmark Tapped"),
            rightPadding: 3,
            bottomPadding: 0.5,
            cardWidth: 80,
          );
          courseCards.add(badgedCourseCard);
        }
        return SizedBox(
          height: 20.5.h,
          child: ListView(
            physics: BouncingScrollPhysics(),
            scrollDirection: Axis.horizontal,
            children: courseCards,
          ),
        );
      },
    );
  }

我该如何解决这个问题?

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    这里,

    coursesCollection = FirebaseFirestore.instance.collection('courses').where('courseID', whereIn: courses);
    

    courses 将是 [],因为 fetchCourses 是一个 async 调用。

    fetchCourses 的返回类型从void 更改为Future&lt;void&gt; 并尝试使用then 回调:

    @override
    void initState() {
      super.initState();
      fetchCourses().then((val) {
        coursesCollection = FirebaseFirestore.instance.collection('courses').where('courseID', whereIn: courses);
        setState(() {});
      });
    }
    

    我还建议使用FutureBuilder 作为更好的选择。

    coursesCollection 为空,这就是您收到另一个错误的原因。仅当coursesCollection 不为空时才渲染StreamBuilder

    coursesCollection != null ? StreamBuilder(...) : SizedBox(),
    

    为了收听用户注册的课程,可以使用另一个 StreamBuilder。这将是一个嵌套的 StreamBuilder 设置。

    StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
      stream: FirebaseFirestore.instance.collection('users').doc(FirebaseAuth.instance.currentUser.uid).snapshots(),
      builder: (context, snapshot) => snapshot.hasData ? StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
        stream: FirebaseFirestore.instance.collection('courses').where('courseID', whereIn: snapshot.data!.data()!['coursesEnrolled']).snapshots(),
        builder: (context, snapshotTwo) {},
      ) : Text('Loading...'),
    ),
    

    【讨论】:

    • 感谢您的快速回复。但我收到以下错误This expression has a type of 'void' so its value can't be used. Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void.
    • Future&lt;void&gt;替换void
    • 感谢@Tirth Patel,这个解决方案奏效了。但间歇性工作。在很短的时间内,它会显示以下错误,然后显示数据。
    • 再次感谢@Tirth Patel 的热心帮助。非常感谢!
    猜你喜欢
    • 2020-04-07
    • 2020-04-04
    • 1970-01-01
    • 2018-11-16
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 2013-04-29
    相关资源
    最近更新 更多