如何用未来的值填充流?

时间:2018-06-20 14:49:05

标签: dart google-cloud-firestore flutter reactive-programming

我正在使用流来监视firestore后端中的更改。可以正常进行更新,但是我没有初始值。

class A {
  final Stream<DocumentSnapshot> _visitorCount =
      Firestore.instance.document('ServerData/serverStatus').snapshots();

  Stream<int> get visitorCount {
    return Observable(_visitorCount)
        .map((DocumentSnapshot doc) => doc['activeUsers'] as int);
  }
}

我可以使用rxdart的{​​{1}}提供一个初始值,但是读出该值会得到一个startWith,我需要提供一个Future<int>int

startWith

我会这样使用它:

static Future<int> f = Firestore.instance
  .collection('ServerData')
  .document('serverStatus')
  .get()
  .then((doc) => doc['activeUsers'] as int);

我提供StreamBuilder( stream: _visitorCount, initialData: 0, builder: (context, snapshot) => Text('${snapshot.data} users logged in') ... 作为初始值,但这当然只是一个临时值。 我敢肯定,这是如此明显,但我仍然努力做到正确。 解决此问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

使用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
    });
  }
}

答案 1 :(得分:1)

结果是我需要解决的问题不需要我将将来的值添加到流中以弥补遗漏的值。我所需要的只是使用Remi Rousselet指出的BehaviorSubject。 但为了完整性:这是您从Future取值并将其推入流中的方法:

Future中的值插入流中

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

  A() {
    _stateSubject = new BehaviorSubject();
    _state = _stateSubject;

    Firestore.instance
        .document('ServerData/serverStatus')
        .snapshots()
        .map((DocumentSnapshot doc) => doc['activeUsers'] as int)
        .listen((int value) {
      _stateSubject.add(value);
    });
  }

  Future<int> get visitorCount => Firestore.instance
      .document('ServerData/serverStatus')
      .get()
      .then((DocumentSnapshot d) => d.data['activeUsers']);
  void addFromFuture() => visitorCount.then((int v) => _state.add(v + 1));
}

通过调用addFromFuture,我可以查询一些将导致Future<int>的值,并使用Subject函数将该值推入add()中。 _state-Subject的所有侦听器都将收到这些更新。

为什么更容易使用BehaviorSubject

作为一个解释,为什么BehaviorSubject使我们避免对Future(从RxJava文档中获取)使用这种笨拙的解决方法:

即使另一个订户迟到了,最新接收到的项目也会被缓冲并正确传送。

答案 2 :(得分:0)

在将有用的东西发送到StreamBuilder之前,Firestore需要一些时间来加载数据。各种快照的hasData属性可在构建时用于对此状态做出反应。

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