Search code examples
flutterdartgoogle-cloud-firestoreasync-awaitfirebase-security

Flutter - How do I use await inside the streambuilder?


I want to use await inside streambuilder. However, if you use async inside, you get an error. On the code below !!!!!!!! That's the part I want to solve. Thank you very much if I can tell you how.

class _MemoStreamState extends State<MemoStream> {
final _fireStore = Firestore.instance;

@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
  stream: _fireStore
      .collection(widget.logInUsrEmail)
      .orderBy('id', descending: false)
      .snapshots(),
  builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (!snapshot.hasData) return LinearProgressIndicator();

    final memos = snapshot.data.documents;
    List<MemoMaterial> memoList = [];

    for (var memo in memos) {
      final memoDocumentID = memo.documentID;
      final memoTitle = await PlatformStringCryptor().decrypt(memo.data['title'], _key);  !!!!!!!!!!
      final memoUsrID = memo.data['usrID'];
      final memoUsrPW = memo.data['usrPW'];
      final memoText = memo.data['text'];
      final memoCreateTime = memo.data['createTime'];

      final memoMaterial = MemoMaterial(
        logInUsrEmail: widget.logInUsrEmail,
        doc: memoDocumentID,
        title: memoTitle,
        usrID: memoUsrID,
        usrPW: memoUsrPW,
        text: memoText,
        createTime: memoCreateTime,
      );
      memoList.add(memoMaterial);
    }

    return Expanded(
      child: new ListView.builder(

Solution

  • You should do something like this :

      Stream<List<MemoMaterial>> memosStream;
    
      Future<MemoMaterial> generateMemoMaterial(Memo memo) async {
        final memoTitle =
            await PlatformStringCryptor().decrypt(memo.data['title'], _key);
    
        return MemoMaterial(
          logInUsrEmail: widget.logInUsrEmail,
          doc: memo.documentID,
          title: memoTitle,
          usrID: memo.data['usrID'],
          usrPW: memo.data['usrPW'],
          text: memo.data['text'];,
          createTime: memo.data['createTime'],
        );
      }
    
      @override
      void initState() {
        memosStream = _fireStore
                .collection(widget.logInUsrEmail)
                .orderBy('id', descending: false)
                .snapshots()
                .asyncMap((memos) => Future.wait([for (var memo in memos) generateMemoMaterial(memo)]));
        super.initState();
      }
      @override
      Widget build(BuildContext context) {
      return StreamBuilder<List<MemoMaterial>>(
        stream: memosStream // Use memostream here
    
    

    asyncMap() will "transform" every new set of Documents into a list of MemoMaterial, and emit this list into the stream when the action is performed.

    Future.wait() allows to perform multiple async requests simultaneously.