Reputation: 3076
Hi I want to deserialise the snapshot from the realtime database to a Company object and add it to a _companies list. But I keep getting an error...
This is what I have so far:
List<Company> _companies = [];
@override
void initState() {
// TODO: implement initState
super.initState();
getItems().then((list){
print("Now the list is here");
setState(() {
for (int i=0; i < list.length; i++) {
Map<String, dynamic> map = list[i];
Company company = new Company.fromMap(map);
_companies.add(company);
}
});
});
}
static Future<List> getItems( ) async {
Completer<List> completer = new Completer<List>();
FirebaseDatabase.instance
.reference()
.child("Companies")
.once()
.then( (DataSnapshot snapshot) {
List map = snapshot.value; //It fails here
completer.complete(map);
} );
return completer.future;
}
This is my Company class:
class Company {
String key;
String category;
String company_name;
String company_url;
String country;
String description;
String email;
String faq_url;
String instagram_url;
String logo_url_image;
String p_category;
String parent_company_ok;
String timestamp;
Company();
Company.fromSnapshot(DataSnapshot snapshot)
: key = snapshot.key,
category = snapshot.value['category'],
company_name = snapshot.value['company_name'],
company_url = snapshot.value['company_url'],
country = snapshot.value['country'],
description= snapshot.value['description'],
email = snapshot.value['email'],
faq_url = snapshot.value['faq_url'],
instagram_url = snapshot.value['instagram_url'],
logo_url_image = snapshot.value['logo_url_image'],
p_category = snapshot.value['p_category'],
parent_company_ok = snapshot.value['parent_company_ok'],
timestamp = snapshot.value['timestamp'];
}
How ever, it fails in getItems( ) on List map = snapshot.value;
. With the exeption: _InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'List<dynamic>'
Also if anyone can provide the code for showing the children in a List widget I would be very happy :)
Here is my data structure in firebase realtime database:
Upvotes: 0
Views: 3561
Reputation: 4741
Well as the error message says snapshot.value is not a List but it is a map so the line List map = snapshot.value; will always fail. Since you are reading Companies node tree from your database this will return a map of maps, something like Map<String, Map<dynamic,dynamic>>
with all data from respective node. I will provide you a function that parse your Json data in Company object and i will left some comments in source code to try explain you the process. It's simple.
List<Company> _parseData(DataSnapshot dataSnapshot) {
List<Company> companyList =new List();
// here you replace List map = snapshot.value with... dataSnapshot.val()
Map<String, dynamic> mapOfMaps = Map.from( dataSnapshot.val() );
//actually dynamic here is another Map, String are the keys like -LXuQmyuF7E... or LXuSkMdJX...
//of your picture example and dynamic other Map
//in next lines we will interate in all values of your map
//remeber that the values are maps too, values has one map for each company.
//The values are Map<String, dynamic>
//in this case String are keys like category, company_name, country, etc...
//and dynamics data like string, int, float, etc
//parsing and adding each Company object to list
mapOfMaps.values.forEach( (value) {
companyList.add(
//here you'll not use fromSnapshot to parse data,
//i thing you got why we're not using fromSnapshot
Company.fromJson( Map.from(value) )
);
});
return companyList;
}
Note you will use Company.fromSnapshot(snapshot) when you read a specific company from your db, something like ...
// just to illustrate
var snapshot = await FirebaseDatabase.instance
.reference()
.child("Companies")
.child(companyId).once();
Company.fromSnapshot( snapshot );
because in this case the snapshot.value is a single map. Well another thing is, take a look at you initState method in your statefull widget, i don't know if is a good approach call setState inside initState method even after a Future execution. This is just an advise.
Upvotes: 3
Reputation: 918
snapshot.value returns a Map and you are using a List to store it. Maybe the easiest solution here is to use the var type to declare your map variable:
var map = snapshot.value;
but it's a good practice to set a type whenever you can to your variables. So, in this case the best option is to set it like this:
Map<dynamic, dynamic> map = snapshot.value;
Check dart's documentation to improve your skills in useing maps and list and how they work Lists docs Maps docs
Upvotes: 1