在加载 Firebase 快照时使用 Flutter 中的 Bloc 流式等待和阻止其他事件

Posted

技术标签:

【中文标题】在加载 Firebase 快照时使用 Flutter 中的 Bloc 流式等待和阻止其他事件【英文标题】:Stream waiting and blocking other events using Bloc in Flutter while loading Firebase snapshots 【发布时间】:2019-08-11 13:04:13 【问题描述】:

我正在使用 Flutter、Firebase Firestore 和 bloc 模式编写应用程序。

当应用程序打开时,我想从 firestore 数据库中加载一些书籍,为此我定义了以下 bloc 代码:

class EditorBloc extends Bloc<BookEvent, BooksState> 

  @override
  BooksState get initialState => BooksLoading();

  EditorBloc();

  Stream<BooksState> _loadBooks() async* 
    final CollectionReference bookPostRef = Firestore.instance.collection('books');
    try 
      Stream<QuerySnapshot> stream = bookPostRef.snapshots();
      await for (QuerySnapshot querySnapshot in stream) 
        List<Book> remoteBooks = List();
        for (var documentSnapshot in querySnapshot.documents) 
          remoteBooks.add(Book.fromDocumentSnapshot(documentSnapshot));
        
        yield BooksLoaded(remoteBooks);
        // If I return here I can dispatch more events but not all the snapshots will be processed
      
     catch (_) 
      yield BooksNotLoaded();
    
  

  Stream<BooksState> _saveBooks(Gym gym, Sector sector, BookHistory booksHistory) async* 
    // Some code
  

  Stream<BooksState> _addBooks(Gym gym, Sector sector, BookHistory booksHistory) async* 
    // Some code
  

  @override
  Stream<BooksState> mapEventToState(BooksState currentState, BookEvent event) async* 

    if (event is LoadBooks) 
      yield* _loadBooks(event.gym, event.sector);
     else if(event is SaveBooks) 
      yield BooksLoading();
      yield* _saveBooks(event.gym, event.sector, event.booksHistory);
     else if (event is AddBook) 
      yield* _addBooks(gym, sector, booksHistory)
    
  

当应用程序启动时,我使用以下代码加载书籍集合:

myBloc.dispatch(LoadBooks());

当书籍加载时我会收到通知,但如果我发送类似这样的其他事件:

myBloc.dispatch(AddBook(newBook));

该事件永远不会被处理,因为EditorBloc 仍在等待方法_loadBooks 中的其他快照。

我应该怎么做才能调度其他事件?

谢谢!

【问题讨论】:

你是故意监听LoadBooks的变化吧? 是的,可以吗?不知道该怎么走 我遇到了同样的问题,不得不将我的查询从 ref.snapshots() 更改为 List&lt;DocumentSnapShot&gt; snapshots = await ref.get() 以获得未来。然后我使用了yield MyState(snapshots.map((snapshot) =&gt; myObject(snapshot)).toList()); 你已经解决了吗? @JoanP.S 你能发布详细的代码来展示你找到的解决方案吗? 【参考方案1】:

解决此问题的一种方法是在 Future 中收听 Stream。一旦该 Future 完成,您就可以开始其他事件。

Future<bool> whenFinishLoading(Stream<BooksState> source) async 
  await for (value in source) 
    // Define a condition expecting a value from Stream
    if (value)  
      return value;
    
  
  return false;

然后您可以使用 Future whenFinishLoading(Stream&lt;BookState&gt;) 等待它完成以开始下一个 Stream 事件。

【讨论】:

以上是关于在加载 Firebase 快照时使用 Flutter 中的 Bloc 流式等待和阻止其他事件的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 未加载 Firebase 快照数据。

Firebase Firestore get() 快照在第二次查询时冻结

Firebase:如何停止收听快照

Firebase 快照未正确解析数据

从 Firebase 数据库快照解析布尔值

在 Flutter 中从 Firebase FireCloud 接收数据时,StreamBuilder 中的快照代码不会被执行