Dart 如何使用来自未来的值填充流?

Dart 如何使用来自未来的值填充流?,dart,google-cloud-firestore,flutter,reactive-programming,Dart,Google Cloud Firestore,Flutter,Reactive Programming,我正在使用流来监视后端的更改。这对于更新来说是可行的,但是我没有得到初始值 class A { Subject<String> _stateSubject; Stream<String> _state; Stream<String> get state { return _state; } A() { _stateSubject = new BehaviorSubject(seedValue: "initial value

我正在使用流来监视后端的更改。这对于更新来说是可行的,但是我没有得到初始值

class A {
  Subject<String> _stateSubject;
  Stream<String> _state;
  Stream<String> get state {
    return _state;
  }

  A() {
    _stateSubject = new BehaviorSubject(seedValue: "initial value");
    _state = _stateSubject.asBroadcastStream();

    Stream fireStoreStream; // your firestore query here
    fireStoreStream.listen((value) {
      _stateSubject.add(value.toString()); // push your new value
    });
  }
}
甲级{ 最终流\u访问者计数= Firestore.instance.document'ServerData/serverStatus'。快照; 流获取访问者计数{ 返回可观察的访问计数 .mapDocumentSnapshot doc=>doc['activeUsers']作为int; } } 我可以使用rxdart的startWith来提供初始值,但是读取这个值会在将来产生结果,我需要向startWith提供一个int

静态未来f=Firestore.instance .收集“服务器数据” .文档“服务器状态” 收到 .thendoc=>doc['activeUsers']作为int; 在这条路上,我是这样使用它的:

StreamBuilder 流:_访问者计数, 初始数据:0, 生成器:上下文,快照=> 文本“${snapshot.data}已登录的用户”。。。 我提供0作为初始值,但这当然只是一个临时值。 我相信这是很明显的,但我仍然努力使它正确。 解决此问题的最佳方法是什么?

使用行为主体提供初始值

class A {
  Subject<String> _stateSubject;
  Stream<String> _state;
  Stream<String> get state {
    return _state;
  }

  A() {
    _stateSubject = new BehaviorSubject(seedValue: "initial value");
    _state = _stateSubject.asBroadcastStream();

    Stream fireStoreStream; // your firestore query here
    fireStoreStream.listen((value) {
      _stateSubject.add(value.toString()); // push your new value
    });
  }
}
使用BehaviorSubject提供初始值

class A {
  Subject<String> _stateSubject;
  Stream<String> _state;
  Stream<String> get state {
    return _state;
  }

  A() {
    _stateSubject = new BehaviorSubject(seedValue: "initial value");
    _state = _stateSubject.asBroadcastStream();

    Stream fireStoreStream; // your firestore query here
    fireStoreStream.listen((value) {
      _stateSubject.add(value.toString()); // push your new value
    });
  }
}

Firestore需要时间加载数据,然后才能将有用的内容发送到StreamBuilder。各种快照的hasData属性可用于在生成时对此状态作出反应

StreamBuilder(
  stream: _visitorCount,
  builder: (context, snapshot) {
    if (!snapshot.hasData) return CircularProgressIndicator(); // Loading..
    // Here the data is loaded and available
  },
)

Firestore需要时间加载数据,然后才能将有用的内容发送到StreamBuilder。各种快照的hasData属性可用于在生成时对此状态作出反应

StreamBuilder(
  stream: _visitorCount,
  builder: (context, snapshot) {
    if (!snapshot.hasData) return CircularProgressIndicator(); // Loading..
    // Here the data is loaded and available
  },
)

事实证明,我需要解决的问题并不需要我在流程中添加未来的价值来弥补遗漏的价值。我所需要的只是使用Remi Rousselet所指出的行为主体。 但为了完整性:以下是您如何从未来获取价值并将其推送到流中:

将未来值插入流中 甲级{ 主题(Subject)国家主题;; 主体状态; 主体获得状态{ 返回状态; } A{ _stateSubject=新行为主体; _state=_statepubject; Firestore.instance .文档“服务器数据/服务器状态” .快照 .mapDocumentSnapshot doc=>doc['activeUsers']作为int .listin值{ _stateSubject.addvalue; }; } Future get visitorCount=>Firestore.instance .文档“服务器数据/服务器状态” 收到 .thenDocumentSnapshot d=>d.data['activeUsers']; void addfromfourture=>visitorCount.thenit v=>\u state.addv+1; } 通过调用addFromFuture,我可以查询一些将产生未来的值,获取该值并使用add函数将其推送到主题中。_state-Subject的所有侦听器都将收到这些更新

为什么使用行为主体更容易? 作为一种解释,为什么BehaviorSubject让我们不用使用这种从文档中获取未来的笨拙解决方法:


即使另一个订阅者来晚了,最近收到的项目也被缓冲并正确传递。

结果表明,我需要解决的问题并不需要我在流中添加未来的一些值来弥补丢失的值。我所需要的只是使用Remi Rousselet所指出的行为主体。 但为了完整性:以下是您如何从未来获取价值并将其推送到流中:

将未来值插入流中 甲级{ 主题(Subject)国家主题;; 主体状态; 主体获得状态{ 返回状态; } A{ _stateSubject=新行为主体; _state=_statepubject; Firestore.instance .文档“服务器数据/服务器状态” .快照 .mapDocumentSnapshot doc=>doc['activeUsers']作为int .listin值{ _stateSubject.addvalue; }; } Future get visitorCount=>Firestore.instance .文档“服务器数据/服务器状态” 收到 .thenDocumentSnapshot d=>d.data['activeUsers']; void addfromfourture=>visitorCount.thenit v=>\u state.addv+1; } 通过调用addFromFuture,我可以查询一些将产生未来的值,获取该值并使用add函数将其推送到主题中。_state-Subject的所有侦听器都将收到这些更新

为什么使用行为主体更容易? 作为一种解释,为什么BehaviorSubject让我们不用使用这种从文档中获取未来的笨拙解决方法:


即使另一个订阅者进来晚了,最近收到的项目也会被缓冲并正确传递。

并且向startWith提供0或任何其他值都不是一个选项?奇怪的是,document.snapshots应该在加载后为您提供初始值,并且可能在加载后提供任何更新。所以,如果您不更新ServerData/serverStatus,那么您的visitorCount流就不会发出任何消息?初始值是什么意思?代码中没有初始值我假设ServerData/serverStatus已包含
在firestore中的文档中。@Edman您是对的,数据流中提供了数据,但我没有找到它,因此我试图以某种方式重新获取它。向startWith提供0或任何其他值不是一个选项?奇怪的是,document.snapshots应该在加载后为您提供初始值,并且可能在加载后提供任何更新。所以,如果您不更新ServerData/serverStatus,那么您的visitorCount流就不会发出任何消息?初始值是什么意思?您的代码中没有初始值我假设ServerData/serverStatus在firestore中已经包含一个文档。@Edman您是对的数据是在流中提供的,但我错过了它,因此我试图以某种方式重新获取它。问题是我在初始化时没有种子值,它需要单独获取。我错过了什么?我试过了,但是没有得到结果。你说的结果是什么意思?我的意思是我创建了流,当它被更新时,我得到了更新的值。但是我没有从数据库中获得初始值。感谢@rémi rousselet让我了解行为主体。我可以让我的示例使用这个rx功能—一个特殊的StreamController,它捕获添加到控制器中的最新项目,并将其作为第一个项目发送给任何新的侦听器。我对你的回答投了赞成票,但我不会把它作为我问题的解决方案,我的问题是如何用未来重新获取错过的事件,并将其保留到现有的流中。我承认我仍然不理解这个问题。我已经做了很多次了,包括分页和使用这些逻辑都没有问题。可能您遗漏了某个特定于您的用例的信息?问题是我在初始化时没有seedValue,它需要单独获取。我错过了什么?我试过了,但是没有得到结果。你说的结果是什么意思?我的意思是我创建了流,当它被更新时,我得到了更新的值。但是我没有从数据库中获得初始值。感谢@rémi rousselet让我了解行为主体。我可以让我的示例使用这个rx功能—一个特殊的StreamController,它捕获添加到控制器中的最新项目,并将其作为第一个项目发送给任何新的侦听器。我对你的回答投了赞成票,但我不会把它作为我问题的解决方案,我的问题是如何用未来重新获取错过的事件,并将其保留到现有的流中。我承认我仍然不理解这个问题。我已经做了很多次了,包括分页和使用这些逻辑都没有问题。也许有一个特定于您的用例的信息您忽略了?