如何在 Flutter 中基于 Future 结果构建 Stream?

Posted

技术标签:

【中文标题】如何在 Flutter 中基于 Future 结果构建 Stream?【英文标题】:How to build a Stream based on a Future result in Flutter? 【发布时间】:2019-11-07 14:50:20 【问题描述】:

我有一个使用 Firebase-storage 和 google-signin 的 Flutter 应用。 我想做的步骤很简单:

1- 使用 Google 登录(完成)。

2- 获取当前用户 ID(完成)。

3- 在为流构建器构建流时使用用户 ID(问题)。

到目前为止,我正在使用Future 来获取当前用户 ID, 然后在Where clause 中注入用户ID

.where('userId', isEqualTo: userId)

这就是我最终的结果:

这是我应该创建流的部分:

  // Get document's snapshots and return it as stream.
  Future<Stream> getDataStreamSnapshots() async 
    // Get current user.
    final User user = await FirebaseAuth().currentUser();
    String userId = user.uid;

    Stream<QuerySnapshot> snapshots =
      db
        .collection(db)
        .where("uid", isEqualTo: userId)
        .snapshots();

    try 
      return snapshots;
     catch(e) 
      print(e);
      return null;
    
  

这是我应该调用和接收流的部分,

...
children: <Widget>[
    StreamBuilder<QuerySnapshot>(
          stream: CALLING THE PREVIOUS FUNCTION,
            builder: (BuildContext context, 
                      AsyncSnapshot<QuerySnapshot> snapshot) 
                if (snapshot.hasData) 
                    ...
                
              ...

但是这段代码不起作用,因为我无法获得 Future 应该返回的值?有什么想法吗?

非常感谢

【问题讨论】:

【参考方案1】:

你永远不应该有Future&lt;Stream&gt;,这是双异步,这是不必要的。只需返回一个Stream,然后您就不必发出任何事件,直到您准备好。

目前尚不清楚try/catch 正在保护什么,因为非Future 的返回不能抛出。如果您返回一个流,也只需在该流上发出任何错误。

您可以将代码重写为:

Stream<QuerySnapshot> getDataStreamSnapshots() async* 
  // Get current user.
  final User user = await FirebaseAuth().currentUser();
  String userId = user.uid;

  yield* db
    .collection(db)
    .where("uid", isEqualTo: userId)
    .snapshots();

async* 函数是异步的,因此您可以使用await。它返回一个Stream,然后您使用yield event;yield* streamOfEvents; 在流上发出事件。

【讨论】:

双异步注释可能有点混乱。有一些合法的用例,比如Future/Stream&lt;List&lt;Stream&gt;&gt; 但我认为他说的是这个案例,而不是一个全球性的解决方案!

以上是关于如何在 Flutter 中基于 Future 结果构建 Stream?的主要内容,如果未能解决你的问题,请参考以下文章

将 Future 类型化结果从函数分配给 Flutter Widget 中的变量

Flutter - 如何在“Future”中显示“snackbar”

如何在 Flutter 的 StreamBuilder 中使用 Future [重复]

如何在 Flutter 中返回 Future<Response>?

使用flutter_local_notifications时如何在Flutter中将Future<Null>转换为Future<dynamic>?

Flutter进阶篇(4)-- Flutter的Future异步详解