Flutter StreamBuilder用于多个Firebase文档

时间:2020-06-26 08:21:55

标签: firebase flutter asynchronous dart

usersCollection.document(user.uid) firebase文档进行更改时,我正在尝试更新Flutter应用。

用户文档更新后,我不仅要从该文档中检索数据,还要从另一个Firebase文档facilitiesCollection.document(...)中检索数据。

我当前的代码

Future<Map> _getCheckedInFacilityData() async {
  Map<String, dynamic> result = {};

  try {
    DocumentSnapshot userDoc =
        await _db.usersCollection.document(user.uid).get();

    if (userDoc.data['checkedIn']) {
      // User is checked in
      DocumentSnapshot facDoc = await _db.facilitiesCollection
          .document(userDoc.data['activeFacilityID'].toString())
          .get();

      result['facilityID'] = userDoc.data['activeFacilityID'];
      result['sessionID'] = userDoc.data['activeSessionID'];
      result['facilityActiveUsers'] = facDoc.data['activeUsers'].length;
      result['facilityName'] = facDoc.data['name'];

      return result;
    }
  } catch (er) {
    debugPrint(er.toString());
  }
  return null;
}
FutureBuilder<Map>(
  future: _getCheckedInFacilityData(),
  builder: (context, map) {
    switch (map.connectionState) {
      case ConnectionState.waiting:
        return Center(child: CircularProgressIndicator());
...

当前正在工作,但是在更改用户文档时页面不会更新。 我已经很长时间没有使用Flutter / Dart了,所以欢迎提出任何想法。

是否可以从StreamBuilder返回由2个单独的文档组成的自定义对象/地图,或者有其他方法可以在我的情况下使用。

1 个答案:

答案 0 :(得分:1)

您当然可以使用Streams asyncMap()完成此操作,然后在StreamBuilder中进行监听

基本算法

获取您第一个数据类型的流,然后获取asyncMap以等待第二个数据类型并同时返回它们

stream.asyncMap(
  (v1) async {
    final v2 = await Future.delayed(Duration(seconds: 1), () => 4);
    return v1 * v2;
  },
);

更接近您的代码

Stream<Map<String, dynamic>> _getCheckedInFacilityData() {

  return _db.usersCollection.document(user.uid).snapshots()
      .asyncMap(
    (userDoc) async {
      final DocumentSnapshot facDoc =
          await _db.facilitiesCollection
      .document(userDoc.data['activeFacilityID'].toString())
      .get();
      final Map<String, dynamic> userMap = userDoc.data;
      final Map<String, dynamic> facMap = facDoc.data;
      return userMap..addAll(facMap);
    },
  );
}

在此函数中,我合并了两个地图-如果两个地图具有相同的键,请小心,在我们的案例中,地图将仅保留最后一个从addAll(facMap)添加的键

最后一步是在屏幕上显示流数据-使用StreamBuilder

StreamBuilder<Map>(
  stream: _getCheckedInFacilityData(),
    builder: (context, snapshot) {
          if (snapshot.hasError) {
            return Text('${snapshot.error}');
          } else if (snapshot.connectionState == ConnectionState.waiting) {
            return LinearProgressIndicator();
          }
          
          return /* some widget that shows your data*/;
        },
      ),