先飘动不响应的地方firestore

问题描述

几个月前,我做了一个功能,我的应用程序正在等待用户文档并做出相应的响应。直到我对项目进行优化并将其更新到最新版本之前,它一直是一种魅力。

如果存在用户文档,则流将产生该文档并关闭流。 如果云Firestore中没有用户数据,该流将产生null并等待文档出现在云中。

// this function doesn't work properly and it should work but `firstWhere` is not
// listening to the stream unless there is a listener already wich makes no sense

static Stream<DocumentSnapshot> get getUserDocumentWhenExists async* {
  User user = FirebaseAuth.instance.currentUser;
  if (user == null) throw 'No user is signed in';

  FirebaseFirestore firebase = FirebaseFirestore.instance;
  CollectionReference usersCollection = firebase.collection('users');
  Stream<DocumentSnapshot> userDocumentStream = usersCollection.doc(user.uid).snapshots();

  userDocumentStream.listen((event) {}); // <= this is here for the code to work

  DocumentSnapshot userDocument = await userDocumentStream.first;
  if (userDocument.exists == false) {
    yield null;
    yield await userDocumentStream.firstWhere((userDocument) {
      // not beeing called without a prevIoUs listener
      return userDocument.exists;
    });
  } else {
    yield userDocument;
  }
}

如果在不删除userDocumentStream.listen((event) {})的情况下运行此代码,它将像更新前一样正常工作。

我的问题是: 这是一个错误吗? 为什么会这样呢?还是我写错了什么?

编辑:我进行了不带Firebase的自定义测试,一切正常。只是在这种特殊情况下,firstWhere()没有收听流

Edit2 :经过更多测试后,我发现userDocumentStream.first之后的所有侦听器均不起作用。现在我更困惑了,我真的需要一些帮助

解决方法

我认为在调用first()之后,即使在first文档中另有说明,订阅也会被取消:

“在内部,该方法在第一个元素之后取消其订阅。这意味着单订阅(非广播)流已关闭,并且在调用此getter之后无法重用。”

我的解决方案:snapshots()创建一个first()流,为firstWhere()创建一个流

final documentReference = usersCollection.doc(user.uid);

final userDocument = await documentReference.snapshots().first;
if (userDocument.exists == false) {
  yield null;
  yield await documentReference.snapshots().firstWhere((userDocument) {
    return userDocument.exists;
  });
} else {
  yield userDocument;
}