I have a class that has several embedded arrays as well as a couple of objects. I'm using Flutter and can't figure out how to read/write to Cloud Firestore.
I can read/write data members that are default types like String and Int. Here is the constructor I'm trying to use to instantiate an object from a DocumentSnapshot:
class GameReview { String name; int howPopular; List<String> reviewers; } class ItemCount { int itemType; int count; ItemCount.fromMap(Map<dynamic, dynamic> data) : itemType = data['itemType'], count = data['count']; } class GameRecord { // Header members String documentID; String name; int creationTimestamp; List<int> ratings = new List<int>(); List<String> players = new List<String>(); GameReview gameReview; List<ItemCount> itemCounts = new List<ItemCount>(); GameRecord.fromSnapshot(DocumentSnapshot snapshot) : documentID = snapshot.documentID, name = snapshot['name'], creationTimestamp = snapshot['creationTimestamp'], ratings = snapshot['ratings'], // ERROR on run players = snapshot['players'], // ERROR on run gameReview = snapshot['gameReview']; // ERROR on run itemCount = ???? }
It works until I add the last 3 members (ratings, players and gameReview). This should be obvious but none the less, it eludes me.
Help!
UPDATE: Here is a sample of the document stored in Cloud Firestore. This is stored in a single document. In other words, I'm not using sub-collections for the embedded objects. I put it into a JSON format for clarity. I hope this helps.
{ "documentID": "asd8didjeurkff3", "name": "My Game Record", "creationTimestamp": 1235434, "ratings": [ 4, 2012, 4 ], "players": [ "Fred", "Sue", "John" ], "gameReview": { "name": "Review 1", "howPopular": 5, "reviewers": [ "Bob", "Hanna", "George" ] }, "itemCounts": [ { "itemType": 2, "count": 3 }, { "itemType": 1, "count": 2 } ] }
UPDATE 2: I didn't put in the whole class definition because I thought it would be obvious to me how to do the rest but alas that was not the case.
I have a list of objects that I want to load.vbandrade's answer is BANG on but I can't quite figure out how I'm supposed to create the list of objects. List.from(...) is looking for an iterator, not a created class. I'm sure it's some variation of creating a new object and then adding it to a list but I'm a little confused. (see edits in class above, specifically, the "itemCounts" member.
How to integrate firebase with flutter android or ios app ? Open firebase, click on get started which will take you to the Add Project screen. Enter the project name and complete the other essential steps. It will take you to your project screen, click on the android icon.
If you came here because of List<dynamic> is not of type List<someType>
error while reading data from firestore, you can just use List.castFrom
Example: List<String> cards = List.castFrom(cardsListFromFirebase);
Checkout Flutter firebase, List<dynamic> is not of type List<String>
load the list from the array and let the framework take care of type casting.
an object is simply a map, like you wrote in your Json. I also use named constructor. ((still learning and dont know how to use the static constructor @ganapat mentioned))
here´s the working code. I kept firebase auth out and used the StreamBuilder widget.
import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'model/firebase_auth_service.dart'; void main() async { runApp(new MyApp()); } class MyApp extends StatelessWidget { final firebaseAuth = new FirebaseAuthService(); MyApp() { firebaseAuth.anonymousLogin(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: FlatButton( color: Colors.amber, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Text("get Game Record"), StreamBuilder<GameRecord>( stream: getGame(), builder: (BuildContext c, AsyncSnapshot<GameRecord> data) { if (data?.data == null) return Text("Error"); GameRecord r = data.data; return Text("${r.creationTimestamp} + ${r.name}"); }, ), ], ), onPressed: () { getGame(); }, )))); } } Stream<GameRecord> getGame() { return Firestore.instance .collection("games") .document("zZJKQOuuoYVgsyhJJAgc") .get() .then((snapshot) { try { return GameRecord.fromSnapshot(snapshot); } catch (e) { print(e); return null; } }).asStream(); } class GameReview { String name; int howPopular; List<String> reviewers; GameReview.fromMap(Map<dynamic, dynamic> data) : name = data["name"], howPopular = data["howPopular"], reviewers = List.from(data['reviewers']); } class GameRecord { // Header members String documentID; String name; int creationTimestamp; List<int> ratings = new List<int>(); List<String> players = new List<String>(); GameReview gameReview; GameRecord.fromSnapshot(DocumentSnapshot snapshot) : documentID = snapshot.documentID, name = snapshot['name'], creationTimestamp = snapshot['creationTimestamp'], ratings = List.from(snapshot['ratings']), players = List.from(snapshot['players']), gameReview = GameReview.fromMap(snapshot['gameReview']); }
snapshot['itemCount']
is an array of objects. map each item in that array to an ItemCount object and return as a List:
itemCounts = snapshot['itemCount'].map<ItemCount>((item) { return ItemCount.fromMap(item); }).toList();
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