0

当从 Firebase 获取数据并将其存储到本地 SQLite 数据库时,我的 StreamBuilder 在更改流后没有刷新,并且流也没有更新;

这是我的代码,用于监听来自 Firebase 的数据更改,然后将这些新聊天写入本地

    /// LISTEN TO THE STREAM FROM FIREBASE AND THEN WRITE THE NEW MESSAGES TO THE LOCAL DATASE

  // Fetch normal messages
      firestore.fetchMessagesStream(chatRoomId).listen((event) async {
        for (QueryDocumentSnapshot message in event.docs) {
           _database.insert(
            'Messages',
            message.data()!,
            conflictAlgorithm: sql.ConflictAlgorithm.replace,
          );
        }
      });
      // Fetch calls
      firestore.fetchCallsStream(chatRoomId).listen((event) async {
        for (QueryDocumentSnapshot call in event.docs) {
          _database.insert(
            'Calls',
            call.data()!,
            conflictAlgorithm: sql.ConflictAlgorithm.replace,
          );
      // Fetch posts
      firestore.fetchPostsStream(chatRoomId).listen((event) async {
        for (QueryDocumentSnapshot post in event.docs) {
          _database.insert(
            'Posts',
            post.data()!,
            conflictAlgorithm: sql.ConflictAlgorithm.replace,
          );
        }
      });

这里是从本地 SQLite 数据库中获取数据的代码:

/// STREAM FOR LISTENING THE CHANGES IN THE LOCAL DATABASE

Rx.combineLatest3(
      _database.query(
       'Messages',
        where: 'chatRoomId = ?',
        whereArgs: [chatRoomId],
        ).asStream(), // Returns the stream of the Messages Table in local databases
      _database.query(
        'Posts',
        where: 'chatRoomId = ?',
        whereArgs: [chatRoomId],
     ).asStream(), // Returns the stream of the Posts Table in local databases
      _database.query(
        'Calls',
        where: 'chatRoomId = ?',
        whereArgs: [chatRoomId],
       ).asStream(), // Returns the stream of the Calls Table in local databases
      (List<Map<String, dynamic>> streamingMessages,
          List<Map<String, dynamic>> streamingPosts,
          List<Map<String, dynamic>> streamingCalls) {
        /// VERY IMPORTANT: THE FOLLOWING PRINT STATEMENT WILL BE PRINT OUT EVERYTIME A NEW CHAT ARRIVE
        /// VERY IMPORTANT: THE FOLLOWING PRINT STATEMENT WILL BE PRINT OUT EVERYTIME A NEW CHAT ARRIVE
        /// VERY IMPORTANT: THE FOLLOWING PRINT STATEMENT WILL BE PRINT OUT EVERYTIME A NEW CHAT ARRIVE
        /// VERY IMPORTANT: THE FOLLOWING PRINT STATEMENT WILL BE PRINT OUT EVERYTIME A NEW CHAT ARRIVE
        /// VERY IMPORTANT: THE FOLLOWING PRINT STATEMENT WILL BE PRINT OUT EVERYTIME A NEW CHAT ARRIVE
        print('MySqlite: chat stream changes!');

        final List<dynamic> contents = [...streamingMessages, ...streamingPosts, ...streamingCalls];

        return contents;
      },
    );
  }

发送新消息时的预期时间线将是:

用户发送了一条消息 --> 触发 Firebase 中的更改 --> 触发 LOCAL SQLite 添加新数据 --> 因为我们的 SQLite 添加了新的聊天,所以我们的 ChatScreen 应该刷新并且还有一个新的调试消息:'MySqlite:聊天流变化!' 由于 ChatScreen 正在侦听 SQLite 数据库流,因此应该在控制台中再次打印出来。

但实际结果是:

用户发送了一条消息——>成功触发了 Firebase 中的更改——>但我没有看到正在刷新的屏幕,也没有在控制台中看到新的调试消息......

我已经为这个问题苦苦挣扎了好几天,我不知道为什么结果不是我想要的,如果我让 ChatScreen 直接听 Firebase,它就可以了!*

更新:

我刚刚发现如果我重建ChatScreen(弹出屏幕,然后再次打开它),或者在发送新消息时设置状态,我可以看到新消息,证明消息发送后确实进入了SQLite数据库,但它只是没有触发 StreamBuilder。因此 Fetching Stream 可能有问题。

回答:

我刚刚发现 SQLite.query 函数不能作为 Stream 获取,我认为我可以使用“asStream”方法,但这没有做任何事情,这是 SQLite 包尚未实现的缺失功能,所以我添加了作为原始 SQLite 包的包装器的sqlbrite 包,它具有一些附加功能,例如将数据作为流查询。^_^

4

1 回答 1

0

我刚刚发现 SQLite.query 函数不能作为 Stream 获取,我认为我可以使用“asStream”方法,但这并没有做任何事情,这是 SQLite 包尚未实现的缺失功能,所以我添加了作为原始 SQLite 包的包装器的sqlbrite 包,它具有一些附加功能,例如以流形式查询数据。^_^

于 2021-05-04T17:27:37.643 回答