简体   繁体   English

Flutter Firebase 实时数据库不在侦听器代码之外存储值

[英]Flutter Firebase real time database not storing values outside of listener code

been stuck on this for a bit.一直坚持这一点。 Firebase Real Time Database using SDK. Firebase 使用 SDK 的实时数据库。

I am able to successfully print the correct data in the original listening event but it does not seem to persist outside of it.我能够在原始监听事件中成功地打印出正确的数据,但它似乎并没有在它之外持续存在。 Been trying a bunch of different things but the docs say this should work.一直在尝试一堆不同的东西,但文档说这应该有效。

Widget build(BuildContext context) {
  Map<dynamic, dynamic> map = {}; 

  DatabaseReference materials =
      FirebaseDatabase.instance.ref('Users/${widget.uid}/materials');

  materials.onValue.listen((DatabaseEvent event) {
    map = event.snapshot.value as Map;
    print(map);
    print(map.keys.elementAt(0).toString());
    print(map.length); //HERE IT PRINTS 4 AS IT SHOULD AND ALL ABOVE DATA CORRECT
  });

  return Scaffold(
    backgroundColor: Colors.grey[400],
    appBar: AppBar(
      automaticallyImplyLeading: false,
      backgroundColor: Colors.grey[600],
      centerTitle: true,
      title: Text(map.length.toString()), //HERE IT PRINTS 0 AND ALL THE REST OF THE CODE USING MAP VALUES ARE NULL
    ),

This is the expected behavior.这是预期的行为。 Since the data is has to come from the.network, it may take some time before it is available and happens asynchronously.由于数据必须来自网络,因此可能需要一些时间才能可用并且异步发生。 Since your rendering code doesn't wait for that (it can't, as that would block the user from using the app), you Text(map.length.toString()) uses the initial value of the map that you gave it here: Map<dynamic, dynamic> map = {} .由于您的渲染代码不会等待它(它不能,因为那样会阻止用户使用该应用程序),您Text(map.length.toString())使用您给它的 map 的初始值这里: Map<dynamic, dynamic> map = {}

The solution is to either store the map in the state of the widget, as calling setState will cause Flutter to redraw the widget, or to use a StreamBuilder to accomplish the same.解决方案是将 map 存储在小部件的 state 中,因为调用setState将导致 Flutter 重绘小部件,或者使用StreamBuilder来完成相同的操作。

An example of that last approach would look something like this:最后一种方法的示例如下所示:

title: StreamBuilder(
  stream: materials.onValue,
  builder: (context, AsyncSnapshot<Event> snapshot) {
    if (snapshot.hasData && !event.hasError && event.data.snapshot.value != null) {
      map = snapshot.snapshot.value as Map
      return Text(map.length.toString())
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM