Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get data from Firebase Realtime Database into list in Flutter?

I am trying to retrieve data from Firebase Realtime Database into a list in Flutter using a model. My list is returning as null when I do this. I have read several other posts about using Firebase with Flutter but have not found a clear answer. Here is my current approach (the object is called a 'need', and I am trying to retrieve and display a list of needs):

Model:

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,
    };
  }
}

Database service with Firebase query:

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;
  }
}

ListView:

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 Realtime Database structure:

Firebase example

What am I doing wrong?

like image 265
most200 Avatar asked Apr 29 '20 17:04

most200


Video Answer


3 Answers

Map<dynamic, dynamic> values = needsSnapshot.data.value; is wrong.

Value is the data, so just use Map<dynamic, dynamic> values = needsSnapshot.value;

Also the object your appending to to the List is not converted..

// 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));
    });

One more thing, I'm not 100% sure on this, but if I declare my List as null I have problems when adding value to it, so I always declare the as empty lists.. So instead of List<Need> needs; I'd use List<Need> needs = [];

Hope you solved it already but if not this should work. I just went through the same problem.. Cheers

like image 170
Vincenzo Avatar answered Oct 24 '22 08:10

Vincenzo


Try this

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);
like image 2
Samie Naseem Avatar answered Oct 24 '22 08:10

Samie Naseem


Just a simple example to get users from firebase realtime database and read once then store and generate user list from it

  final List<User> list = [];

  getUsers() async {
    final snapshot = await FirebaseDatabase.instance.ref('users').get();

    final map = snapshot.value as Map<dynamic, dynamic>;

    map.forEach((key, value) {
      final user = User.fromMap(value);

      list.add(user);
    });
  }
class User {

  final String name;
  final String phoneNumber;

  const User({
    required this.name,
    required this.phoneNumber,
  });

  factory User.fromMap(Map<dynamic, dynamic> map) {
    return User(
      name: map['name'] ?? '',
      phoneNumber: map['phoneNumber'] ?? '',
    );
  }
}

like image 2
Burhan Khanzada Avatar answered Oct 24 '22 08:10

Burhan Khanzada