web-dev-qa-db-fra.com

Comment charger un tableau et un objet à partir de Cloud Firestore dans Flutter

J'ai une classe qui a plusieurs tableaux intégrés ainsi que quelques objets. J'utilise Flutter et je ne sais pas comment lire/écrire dans Cloud Firestore.

Je peux lire/écrire des membres de données qui sont des types par défaut tels que String et Int. Voici le constructeur que j'essaie d'utiliser pour instancier un objet à partir d'un 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 = ????
 }

Cela fonctionne jusqu'à ce que j'ajoute les 3 derniers membres (évaluations, joueurs et gameReview). Cela devrait être évident, mais néanmoins, cela m'échappe.

Aidez-moi!

UPDATE: Voici un exemple du document stocké dans Cloud Firestore. Ceci est stocké dans un seul document. En d'autres termes, je n'utilise pas de sous-collections pour les objets incorporés. Je l'ai mis dans un format JSON pour plus de clarté. J'espère que ça aide.

 {
   "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
     }
   ]
 }

MISE À JOUR 2: Je n’ai pas précisé la définition de la classe car je pensais que la façon de faire le reste était évidente, mais hélas, ce n’était pas le cas.

J'ai une liste d'objets que je veux charger. La réponse de vbandrade est BANG mais je n'arrive pas à comprendre comment je suis censé créer la liste d'objets. List.from (...) recherche un itérateur, pas une classe créée. Je suis sûr que c'est une variante de créer un nouvel objet puis de l'ajouter à une liste, mais je suis un peu confus. (voir les modifications dans la classe ci-dessus, en particulier le membre "itemCounts".

Merci!!!

4
JustLearningAgain

chargez la liste à partir du tableau et laissez le cadre s'occuper du transtypage.

un objet est simplement une carte, comme vous l'avez écrit dans votre Json. J'utilise aussi le constructeur nommé. ((toujours en train d'apprendre et ne sais pas comment utiliser le constructeur statique mentionné par @ganapat))

voici le code de travail. J'ai gardé l'autorisation de base de feu et utilisé le widget StreamBuilder.

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'] est un tableau d'objets. mappez chaque élément de ce tableau sur un objet ItemCount et retournez-le sous forme de liste:

    itemCounts = snapshot['itemCount'].map<ItemCount>((item) {
      return ItemCount.fromMap(item);
    }).toList();
4
vbandrade

Les packages Firebase renvoient des types de liste pour les types Array/List présents dans un instantané. Essayez de convertir Liste en Liste ou Liste avant d’affecter des variables. Et pour l’objet GameReview, vous tentez actuellement d’affecter un objet Map à l’objet, comme vous le verriez dans de nombreux exemples de codes voltigeurs.

class GameReivew{

  static GameReivew fromMap(Map<String, dynamic> map){
    GameReivew gameReivew = new GameReivew();
    gameReivew.name = map["name"];
    gameReivew.howPopular = map["howPopular"];
    ....

    return gameReivew;
  }
}

0
Ganapat