【问题标题】:Building widget with data from firebase in flutter returning empty widget在颤振返回空小部件时使用来自firebase的数据构建小部件
【发布时间】:2021-10-25 10:34:12
【问题描述】:

这是我尝试过的代码,但每次运行它都会返回一个空的小部件。似乎列表在 then() 调用结束时被清空了。

final database = FirebaseDatabase.instance.reference();
final reviews = database.child("books/12345/reviews");

    Widget getReviewCards(DatabaseReference reviews) {
        List<Widget> reviewList = <Widget>[];
    
        reviews.once().then((DataSnapshot snapshot) {
          final data = new Map<dynamic, dynamic>.from(snapshot.value);
          data.forEach((key, value) { 
             reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
          });
    
        });
        return Column(children: reviewList);
      }

有谁知道怎么回事?

【问题讨论】:

    标签: flutter firebase-realtime-database


    【解决方案1】:

    数据是从 Firebase(和大多数现代云 API)异步加载的,这会导致您的代码未按您期望的顺序执行。添加一些日志记录使这一点最容易看到:

    print('Before loading data');
    reviews.once().then((DataSnapshot snapshot) {
      print('Loaded data');
    });
    print('After loading data');
    

    如果你运行这段代码,你会得到:

    加载数据之前

    加载数据后

    加载数据

    这可能不是您所期望的,但它确实完美地解释了为什么您的小部件是空的:在您返回小部件时还没有发生任何 reviewList.add(...) 调用。


    您必须返回Future&lt;Widget&gt;,而不是返回Widget,这是将来返回小部件的承诺:

    Future<Widget> getReviewCards(DatabaseReference reviews) { // ? Change return type
      return reviews.once().then((DataSnapshot snapshot) { // ? Add return
        final data = new Map<dynamic, dynamic>.from(snapshot.value);
        List<Widget> reviewList = <Widget>[];
    
        data.forEach((key, value) { 
           reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
        });
        return Column(children: reviewList); // ? Moved up    
      });
    }
    

    您还可以使用 Dart 的 asyncawait 关键字来使上面的内容更加熟悉:

    Future<Widget> getReviewCards(DatabaseReference reviews) async {
      DataSnapshot snapshot = await reviews.once();
      final data = new Map<dynamic, dynamic>.from(snapshot.value);
      List<Widget> reviewList = <Widget>[];
    
      data.forEach((key, value) { 
         reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
      });
      return Column(children: reviewList);
    }
    

    如果您想在 UI 中显示小部件,您需要将其包装在 FutureBuilder 中。


    另见:

    【讨论】:

      猜你喜欢
      • 2020-05-30
      • 2020-09-07
      • 1970-01-01
      • 2019-12-27
      • 2020-06-05
      • 2021-11-25
      • 1970-01-01
      • 2020-04-13
      • 2022-10-14
      相关资源
      最近更新 更多