如何从 Firebase 实时数据库中获取数据到 Flutter 中的列表中?

Posted

技术标签:

【中文标题】如何从 Firebase 实时数据库中获取数据到 Flutter 中的列表中?【英文标题】:How to get data from Firebase Realtime Database into list in Flutter? 【发布时间】:2020-08-13 21:50:48 【问题描述】:

我正在尝试使用模型将 Firebase 实时数据库中的数据检索到 Flutter 中的列表中。当我这样做时,我的列表返回为空。我已经阅读了其他几篇关于在 Flutter 中使用 Firebase 的文章,但还没有找到明确的答案。这是我目前的方法(该对象称为“需求”,我正在尝试检索并显示需求列表):

型号:

import 'package:firebase_database/firebase_database.dart';

class Need 
  final String id;
  final String imageUrl;
  final String caption;
  final String title;

  Need(
    this.id,
    this.imageUrl,
    this.caption,
    this.title,
  );

  Need.fromSnapshot(DataSnapshot snapshot) :
    id = snapshot.key,
    imageUrl = snapshot.value["imageUrl"],
    caption = snapshot.value["caption"],
    title = snapshot.value["postTitle"];

  toJson() 
    return 
      "imageUrl": imageUrl,
      "caption": caption,
      "title": title,
    ;
  

带有 Firebase 查询的数据库服务:

import 'package:firebase_database/firebase_database.dart';
import 'package:Given_Flutter/models/need_model.dart';

class DatabaseService 

  static Future<List<Need>> getNeeds() async 
    Query needsSnapshot = await FirebaseDatabase.instance
      .reference()
      .child("needs-posts")
      .orderByKey();

    print(needsSnapshot); // to debug and see if data is returned

    List<Need> needs;

    Map<dynamic, dynamic> values = needsSnapshot.data.value;
    values.forEach((key, values) 
      needs.add(values);
    );

    return needs;
  

列表视图:

import 'package:flutter/material.dart';
import 'package:Given_Flutter/models/need_model.dart';
import 'package:Given_Flutter/services/database_service.dart';
import 'package:Given_Flutter/need_view.dart';

class Needs extends StatefulWidget 
  static final String id = 'needs_screen';

  @override
  _NeedsState createState() => _NeedsState();


class _NeedsState extends State<Needs> 
  List<Need> _needs = [];

  @override
  void initState() 
    super.initState();
    _setupNeeds();
  

  _setupNeeds() async 
    List<Need> needs = await DatabaseService.getNeeds();
    setState(() 
      _needs = needs;
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: RefreshIndicator(
        onRefresh: () => _setupNeeds(),
        child: ListView.builder(
          itemCount: _needs.length,
          itemBuilder: (BuildContext context, int index) 
            Need need = _needs[index];
            return NeedView(
              need: need,
            );
          
        )
      )
    );
  

Firebase 实时数据库结构:

Firebase example

我做错了什么?

【问题讨论】:

你的调试打印输出什么? @GrahamD 这行显示错误: Map values = needsSnapshot.data.value;错误:没有为类 'Query' 定义 getter 'data'。 @GrahamD 我已尝试删除该行和以下 forEach 循环,以专注于我是否从 Firebase 获取数据。当我这样做时,调试日志从不打印快照数据,即使我有一个打印行。我不知道是因为该部分没有被执行还是快照为空。相反,调试日志显示错误“在 null 上调用了 getter 'length'。”,这是有道理的,因为返回到 ListView 的需求列表是空的。 尝试在代码行中使用 needsSnapshot.value 而不是 needsSnapshot.data.value: Map values = needsSnapshot.data.value;我建议你把更多的印刷声明作为战略要点,看看你实际得到了什么。我不认为你可以打印快照,你只会得到快照的实例,你必须打印它的属性,例如。 .key, .value 【参考方案1】:

Map&lt;dynamic, dynamic&gt; values = needsSnapshot.data.value; 错误。

值是数据,所以只需使用Map&lt;dynamic, dynamic&gt; values = needsSnapshot.value;

您附加到列表的对象也没有转换..

// wrong
Map<dynamic, dynamic> values = needsSnapshot.data.value;
    values.forEach((key, values) 
      needs.add(values);
    );

// correct
Map<dynamic, dynamic> values = needsSnapshot.data.value;
    values.forEach((key, values) 
      needs.add(Need.fromSnapshot(values));
    );

还有一件事,我对此不是 100% 确定的,但是如果我将 List 声明为 null 我在为其添加值时会遇到问题,所以我总是将其声明为空列表。 所以我会使用List&lt;Need&gt; needs = [];而不是List&lt;Need&gt; needs;

希望您已经解决了它,但如果没有,这应该可以。我刚刚遇到了同样的问题.. 干杯

【讨论】:

我设法根据您的解决方案获取数据,但是,当我返回列表时,它是空的(因为返回发生在将数据添加到 forEach() 中的列表之前)。你知道我能做些什么,这样在我的 forEach() 完成之前返回不会执行吗?它还告诉我查询之前的等待什么也不做。 @DanCrisan 嗨,问题应该是你没有将你的方法声明为async 这就是为什么await 没有做任何事情并且它返回一个空的List 它不等待结果填充它并返回声明的空。让我知道这是否解决了它。干杯。 您好,我的方法肯定是声明为async的,否则我认为尝试使用await时会出错。相反,我只是收到一个警告,说它没有做任何事情。如果我在查询结束时使用 .once() 之类的东西,那么 await 可以工作,但是,它会将我的查询转换为 DataSnapshot,而我需要它是一个查询。 @DanCrisan 请分享一些代码,以便我查看并尝试找出问题;) 我已经把代码贴在这里了:***.com/q/64277935/10544887【参考方案2】:

试试这个

needsSnapshot.once().then((DataSnapshot snapshot)
  print(snapshot.value.entries.length);

  for (var val in snapshot.value.entries)
    needs.add(new Need(val.id, val.imageUrl,val.caption,val.title));
    //print(val.value.toString());
  
    //print(needs.length);

【讨论】:

【参考方案3】:

请注意,如果上述方法有效,则可以实现以下效果:

List<Need> yourNeeds=[];
await firestore.collection("Need")
        .getDocuments()
        .then((QuerySnapshot snapshot) 
       snapshot.documents.forEach((f) 
            Needs obj= new Need();
       
        obj.field1=f.data['field1'].toString();
        obj.field2=f.data['field2'].toDouble();

        //Adding value to your Need list
        yourNeeds.add(obj);
);

【讨论】:

【参考方案4】:

创建一个模型来容纳对象。在其中创建一个方法,如下所示,

  ModelName.fromJson(Map<String, dynamic> json) 
    property1 = json['property1'];
    property2 = json['property2'];
  

使用以下方法直接将firebase数据快照转换为模型

databaseRef.once().then((DataSnapshot snapshot) 
      for(var data in snapshot.value)
        
          var model = Model.fromJson(Map<String, dynamic>.from(data));
          logger.i(model.iponame);
        
    );

【讨论】:

以上是关于如何从 Firebase 实时数据库中获取数据到 Flutter 中的列表中?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 firebase 实时数据库中获取子值?

如何从 Firebase 实时数据库中检索/获取项目

如何从 Firebase 中的实时数据库中获取数组

如何从 Flutter 中的 Firebase 实时数据库中按 categoryId 获取产品?

我如何从firebase实时数据库中获取所有数据

Swift 和 Firebase 实时数据库:如何获取对象的数量?