【问题标题】:Convert Flutter stream from Firebase to ints将 Flutter 流从 Firebase 转换为整数
【发布时间】:2020-06-13 02:38:38
【问题描述】:

我有一个具有聊天功能的 Flutter 应用程序,其中的聊天记录存储在 Firebase 数据库中。我有一个BottomNavigationBar,它有一个用于聊天的图标按钮。如果有任何未读聊天,我会在此图标上显示一个徽章:

               BottomNavigationBarItem(
                  icon: new Stack(
                    children: <Widget>[
                      ImageIcon(AssetImage('images/icons.png')),
                      _unreadCount != null && _unreadCount > 0 ? Positioned(
                        right: 0,
                        child: new Container(
                          padding: EdgeInsets.all(1),
                          decoration: new BoxDecoration(
                            color: Colors.red,
                            borderRadius: BorderRadius.circular(6),
                          ),
                          constraints: BoxConstraints(
                            minWidth: 12,
                            minHeight: 12,
                          ),
                          child: new Text(
                            '$_unreadCount',
                            style: new TextStyle(
                              color: Colors.white,
                              fontSize: 8,
                            ),
                            textAlign: TextAlign.center,
                          ),
                        ),
                      ) : null
                    ].where((c) => c != null).toList(),
                  ),
                  title: Text('Chats', style: TextStyle(fontWeight: FontWeight.w500))
              ),

我使用返回Future&lt;int&gt; 的方法获取_unreadCount。它将查询 chats firebase 数据库并返回未读聊天的数量:

Future<int> getUnreadCount() async {

    bool isLoggedIn = await connection.isUserLoggedIn();
    int count = 0;

    if(isLoggedIn) {
      int userId = await _getUserId();

      final QuerySnapshot chatsQuerySnapshot =
        await Firestore.instance.collection("chats")
          .where("userIds", arrayContains: userId)
          .getDocuments();

      final List<DocumentSnapshot> documents = chatsQuerySnapshot.documents;

      if(documents != null && documents.isNotEmpty) {
        for (DocumentSnapshot chatsSnapshot in documents) {
          if(chatsSnapshot['unread'] as bool) {
            count++;
          }
        }
      }
    }

    return count;
  }

但是,因为这将返回 Future,所以只有在重建 BottomNavigationBar 时(即当我单击另一个选项卡时)并且调用 Future 方法时,徽章才会更新。

我需要一个返回 Stream 的方法,但我找不到任何可以按我想要的方式工作的示例。在我看来,流仅在返回数据集合/列表时使用,但我只想要一个int。我对响应式编程知之甚少,而且我是新手,但是如何以这种方式查询 Firebase?

【问题讨论】:

    标签: firebase flutter reactive-programming


    【解决方案1】:

    这是map 函数的确切用例:只需将BottomNavigationBar 中的相关小部件包装在StreamBuilder 中,该StreamBuilder 将Firebase 流的映射版本作为参数。请参阅以下(未经测试的)Stream&lt;int&gt;,您可以在 StreamBuilder 中使用:

    Firestore.instance.collection("chats")
          .where("userIds", arrayContains: userId)
          .snapshots()
          .map((snapshot) {
            return snapshot.documents.fold(0, (count, doc) {
              return (doc['unread'] as bool) ? count + 1 : count;
            });
          });
    

    使用 Dart 中为Lists/Iterables 提供的众多方法之一,fold 调用可能会更干净,但我会留给你。

    这是一个 Future&lt;int&gt;,您可以为 FutureBuilder 制作,如 cmets 中所述:

    /// Returns the userId if the user is logged in, or null otherwise
    Future<int> userIdWrapper() async {
        final isLoggedIn = await connection.isUserLoggedIn();
        return isLoggedIn ? await _getUserId() : null;
    }
    

    【讨论】:

    • 感谢您的回答!看起来很有希望,但正如你所看到的,我有几个调用是 awaiting 一些未来值(如 connection.isUserLoggedIn()_getUserId()。如何在返回 Stream 的方法中使用它们?
    • 虽然您可以使用 RxDart 提供的一些实用程序将数据保存在同一个流中,但最好将 StreamBuilder 与我给您的流包装到 FutureBuilder 中,然后使用在FutureBuilder 的构建方法中提供的结果来构建StreamBuilder
    • 因此,您可以创建一个异步函数,该函数返回一个 Future&lt;int&gt;,如果用户未登录则返回 null,如果用户未登录则返回 userId 的 int。
    • 你能提供一些示例代码吗?我不明白我会怎么做..
    • 当然;我举了一个示例,说明您可以为将来创建的方法作为对我的答案的编辑。你知道如何使用 FutureBuilder 和 StreamBuilder 吗?
    猜你喜欢
    • 2020-07-07
    • 2021-10-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-21
    相关资源
    最近更新 更多