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?
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
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);
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'] ?? '',
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With