Firebase 颤振-接收并修改流中的数据

Firebase 颤振-接收并修改流中的数据,firebase,flutter,google-cloud-firestore,stream-builder,Firebase,Flutter,Google Cloud Firestore,Stream Builder,我正在尝试执行以下操作: 侦听Firestore流,以便在添加新文档时,StreamBuilder将接收、修改并呈现该文档 “修改”获取包含Firestore UID的流数据,使用该UID从Firestore获取数据,然后用该数据填充StreamBuilder 因此,流程是:添加新文档->流获取文档->函数从该文档获取UID->函数使用该UID从Firestore获取更多数据->函数返回用新数据填充StreamBuilder 我目前的设置如下——这是可行的,但FutureBuilder显然是在每

我正在尝试执行以下操作:

  • 侦听Firestore流,以便在添加新文档时,StreamBuilder将接收、修改并呈现该文档
  • “修改”获取包含Firestore UID的流数据,使用该UID从Firestore获取数据,然后用该数据填充StreamBuilder

    因此,流程是:添加新文档->流获取文档->函数从该文档获取UID->函数使用该UID从Firestore获取更多数据->函数返回用新数据填充StreamBuilder

    我目前的设置如下——这是可行的,但FutureBuilder显然是在每次重建小部件时调用Firestore,没有人希望这样

    
    上游;
    void initState(){
    super.initState();
    上游=aStream();
    }
    流aStream(){
    返回Firestore.instance
    .collection('FirstLevel')
    .文档(ownUID(与流无关))
    .collection('SecondLevel')
    .快照();
    }
    未来processStream(列表流数据)异步{
    List futureData=List();
    用于(streamData中的var文档){
    Map dataToReturn=Map();
    DocumentSnapshot userDoc=等待Firestore.instance
    .collection('FirstLevel')
    .文档(流中其他用户的UID)
    .get();
    dataToReturn['i']=userDoc['i'];
    futureData.add(dataToReturn);
    }
    返回未来数据;
    }
    ...
    ...
    //实际的小部件
    扩大(
    孩子:StreamBuilder(
    溪流:上游,
    生成器:(上下文,快照){
    //错误/空处理
    回归未来建设者(
    未来:processStream(快照、数据、文档),
    生成器:(上下文,futureSnap){
    //错误/空处理
    返回ListView.builder(
    收缩膜:对,
    itemCount:futureSnap.data.length,
    滚动方向:轴垂直,
    itemBuilder:(上下文,索引){
    //继续填充
    });
    });
    }),
    ),
    
    处理这种流的最佳方法是什么?创建一个方法,其中来自Firestore流的数据被修改,然后返回,而根本不需要ListView.builder

    编辑:我尝试创建自己的流,如下所示:

      Stream<Map<String, dynamic>> aStream2() async* {
    
        QuerySnapshot snap = await Firestore.instance
            .collection(FirstLevel)
            .document(OWN UID)
            .collection(SecondLevel)
            .getDocuments();
    
        for (var doc in snap.documents) {
          Map<String, dynamic> data = Map<String, dynamic>();
          DocumentSnapshot userDoc = await Firestore.instance
              .collection(FirstLevel)
              .document(OTHER USERS UID RECEIVED FROM STREAM)
              .get();
    
          data['i'] = userDoc['i'];
    
          yield data;
        }
      }
    
    流aStream2()异步*{
    QuerySnapshot snap=wait Firestore.instance
    .收集(一级)
    .文档(自己的UID)
    .收集(二级)
    .getDocuments();
    用于(管理单元文档中的var文档){
    地图数据=地图();
    DocumentSnapshot userDoc=等待Firestore.instance
    .收集(一级)
    .文档(从流接收的其他用户UID)
    .get();
    数据['i']=userDoc['i'];
    产量数据;
    }
    }
    

    但是,当新文档添加到第二级集合时,流不会被触发/更新。

    好的,我想我找到了解决方案的路径。我从流中获取数据,对其进行修改,然后在一个方法中将其交给StreamBuilder,而不再需要FutureBuilder。正如克里斯托弗·摩尔(Christopher Moore)在评论中提到的那样,关键在于
    等待
    。stream方法如下所示:

      Stream<Map<String, dynamic>> aStream2() async* {
    
        QuerySnapshot snap = await Firestore.instance
            .collection(FirstLevel)
            .document(OWN UID)
            .collection(SecondLevel)
            .getDocuments();
    
        for (var doc in snap.documents) {
          Map<String, dynamic> data = Map<String, dynamic>();
          DocumentSnapshot userDoc = await Firestore.instance
              .collection(FirstLevel)
              .document(OTHER USERS UID RECEIVED FROM STREAM)
              .get();
    
          data['i'] = userDoc['i'];
    
          yield data;
        }
      }
    
    Stream()异步流*{
    List DATATORETRETURN=List();
    Stream=Firestore.instance
    .收集(一级)
    .文档(自己的UID)
    .收集(二级)
    .快照();
    等待(QuerySnapshot q在流中){
    对于(q.documents中的var文档){
    Map dataMap=Map();
    DocumentSnapshot userDoc=等待Firestore.instance
    .collection('UserData')
    .document(doc[“其他用户数据变量])
    .get();
    dataMap['i']=userDoc['i'];
    //...//
    dataToReturn.add(dataMap);
    }
    产生数据返回;
    }
    }
    

    然后,StreamBuilder会按照我的要求填充修改后的数据。

    我发现自己正在使用这个工具,在我的应用程序中使用Dash聊天软件包实现一个聊天系统。我认为在流上使用map函数可能会更干净一些,下面是一个示例:

    Stream<List<ChatMessage>> getMessagesForConnection(
      String connectionId) {
    return _db
        .collection('connections')
        .doc(connectionId)
        .collection('messages')
        .snapshots()
        .map<List<ChatMessage>>((event) {
      List<ChatMessage> messages = [];
    
      for (var doc in event.docs) {
        try {
          messages.add(ChatMessage.fromJson(doc.data()));
        } catch (e, stacktrace) {
          // do something with the error
        }
      }
      return messages;
    });}
    
    流getMessagesForConnection(
    字符串连接ID){
    返回_db
    .collection('连接')
    .doc(连接ID)
    .collection('消息')
    .快照()
    .map((事件){
    列表消息=[];
    for(event.docs中的var doc){
    试一试{
    messages.add(ChatMessage.fromJson(doc.data());
    }捕获(e,堆栈跟踪){
    //对这个错误做点什么
    }
    }
    返回消息;
    });}
    
    您可以通过使用
    async*
    wait for
    从头开始创建流来实现这一点。你可以阅读更多关于这个的信息。谢谢。我确实尝试将流更改为自定义,并为StreamBuilder生成修改后的结果,但在将文档添加到Firestore集合时遇到了无法触发流的问题(因为StreamBuilder是由从自定义流返回的列表流提供的,而不是像我提供的示例中那样从Firestore本身)。我是否看错了这个流?