【问题标题】:Flutter StreamBuilder returns null from FirestoreFlutter StreamBuilder 从 Firestore 返回 null
【发布时间】:2019-10-01 12:49:36
【问题描述】:

这个想法是在 Firebase 的集合中显示来自随机文档的字符串。一个简单的函数 getRandom() 检索文档总数并生成一个随机整数 r,该整数被馈送到 Firebase 实例中。

应用中的输出始终为null。

StreamBuilder(
        initialData: Words(),
          stream: getWords(),
          builder: (context, snapshot){

            if(!snapshot.hasData){
              return Center(child: Text("NO DATA"));
            }else {
              var r = snapshot.data;
              return Center(child: Text("${r.english}"));
            }
      })
Stream<Words> getWords() async* {
  int r = await getRandom();

  print("RANDOM NO: " + "$r");

  Firestore.instance.document("vocabs/foods/words/$r")
      .get()
      .then((snapshot){
    try {
      return Words().english;

    } catch(e){
      print("ERROR");
      return null;
    }
  });
}

class Words{

  Words(): super();

  String english;

  Words.fromSnapshot(DocumentSnapshot snapshot)
  : english = snapshot.data["english"];
}

【问题讨论】:

  • 对于异步生成器,关键字 yield 或 yield* 不是 return 吗?此外,似乎返回类型应该是Stream&lt;String&gt;,因为您正在产生Word 的english 字符串。
  • @DanielV。 Stream&lt;String 确实更有意义。 yield 在 then - 回调中是不可能的。它必须是return,但到目前为止它仍然返回null。

标签: firebase dart flutter google-cloud-firestore


【解决方案1】:

我为您构建了一段示例代码,为您提供一些选项来实现您想做的事情:

import 'dart:async';

class Word {    
  final String english;
  const Word(this.english);
}

Future<Iterable<Word>> get firebaseSnapshot async => [ Word('aWord'), Word('bWord'), Word('cWord') ];

Stream<String> getEnglishWords() async* {
  yield* await firebaseSnapshot.then((words) => Stream.fromIterable(words.map((w) => w.english)));
}

Stream<String> getEnglishWords2() async* {    
  final words = await firebaseSnapshot.then((words) => words.map((w) => w.english));
  yield* Stream.fromIterable(words);
}

Stream<String> getEnglishWords3() async* {    
  final snapshot = await firebaseSnapshot;
  for(final word in snapshot) {
    yield word.english;
  }  
}

main() async {
  await for(final englishWord in getEnglishWords()) {
    print(englishWord);
  }

  await for(final englishWord in getEnglishWords2()) {
    print(englishWord);
  }

  await for(final englishWord in getEnglishWords3()) {
    print(englishWord);
  }
}

选项 2 是我会使用的选项。围绕它有一些重要的性能考虑。我正在回想关于它的讲座......不,不记得......如果我找到它,我会更新你。

【讨论】:

  • 首先,非常感谢您抽出宝贵的时间。我没有那么有经验,所以我在理解如何实现您的示例代码方面有点挣扎。如我所见,没有Firestore.instance 可以确定我的 Firestore 数据库中的路径。如何将其添加到 getEnglishWords 函数中?另外,我无法将async 标签添加到主函数中。我假设,在build 小部件中,仍然需要有一个StreamBuilder,但我无处可添加async。再次,非常感谢!
  • 我的示例代码是为了模仿 Firestore 的工作方式。里面没有实例。我建议暂时跳过异步生成器并简化您的代码。另一个入门者:gist.github.com/daniel-v/1fbe7697ae970cb98ab12eb1bed999b8FutureBuilder 类文档非常好。 docs.flutter.io/flutter/widgets/FutureBuilder-class.html
  • 我必须在Words 类中添加我的Words.fromSnapshot 行,这样我才能在getWords 函数中使用.fromSnapshot。但是,它仍然返回 Words 而不是 Future&lt;String&gt; 因此我在该函数中遇到错误。
  • 我又检查了一遍,我意识到我只需要返回word.toString()。我的错误,它现在终于起作用了。我已经为此工作了几天!谢谢你,丹尼尔。感谢您的帮助!
猜你喜欢
  • 2020-07-12
  • 2021-04-19
  • 2021-01-28
  • 2020-12-19
  • 2020-10-01
  • 2023-01-16
  • 2021-07-26
  • 2022-01-22
  • 2020-11-07
相关资源
最近更新 更多