如何在Flutter

时间:2018-06-12 02:37:20

标签: google-cloud-firestore flutter

我有一个包含多个嵌入式数组的类以及一些对象。我正在使用Flutter,无法弄清楚如何读取/写入Cloud Firestore。

我可以读/写像String和Int这样的默认类型的数据成员。这是我试图用来从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 = ????
 }

直到我添加最后3个成员(评级,玩家和gameReview)才有效。这应该是显而易见的,但不过,它让我望而却步。

帮助!

更新: 以下是存储在Cloud Firestore中的文档示例。这存储在单个文档中。换句话说,我没有为嵌入对象使用子集合。为清楚起见,我把它放到JSON格式中。我希望这会有所帮助。

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

更新2: 我没有提到整个班级的定义,因为我认为对我来说如何做其余的事情是显而易见的,但事实并非如此。

我有一个我要加载的对象列表.vbandrade的答案是BANG,但我不知道我应该如何创建对象列表。 List.from(...)正在寻找迭代器,而不是创建的类。我确定这是创建一个新对象然后将其添加到列表中的一些变化,但我有点困惑。 (请参阅上面的类中的编辑,特别是“itemCounts”成员。

感谢!!!

4 个答案:

答案 0 :(得分:9)

如果您是从Firestore读取数据时因List<dynamic> is not of type List<someType>错误而来这里的,则可以只使用List.castFrom

示例: List<String> cards = List.castFrom(cardsListFromFirebase);

结帐Flutter firebase, List<dynamic> is not of type List<String>

答案 1 :(得分:6)

从数组中加载列表,让框架处理类型转换。

一个对象只是一个地图,就像你在Json中写的一样。我也使用命名构造函数。 ((仍在学习,不知道如何使用提到的静态构造函数@ganapat))

这是工作代码。我保留了firebase auth,并使用了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']是一个对象数组。将该数组中的每个项映射到ItemCount对象并作为List返回:

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

答案 2 :(得分:0)

Firebase软件包返回快照中存在的阵列/列表类型的列表类型。在分配变量之前,尝试将List转换为List或List。 对于GameReview对象,目前,您正在尝试将Map的对象分配给对象, 如果你在GameReview类中编写静态fromMap方法会有所帮助,它接受map参数并将其转换为所需的对象结构,就像许多flutters示例代码中所见。

&#13;
&#13;
class GameReivew{

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

    return gameReivew;
  }
}
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您可以使用JsoSerializable()

将以下依赖项添加到pubspec.yaml

dependencies:
  # Your other regular dependencies here
  json_annotation: ^2.0.0

dev_dependencies:
  # Your other dev_dependencies here
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

并设置您的课程JsonSerializable()

import 'package:json_annotation/json_annotation.dart';

part 'game.g.dart';

@JsonSerializable()
 class GameReview {
   String name;
   int howPopular;
   List<String> reviewers;

  GameReview();

  factory GameReview.fromJson(Map<String, dynamic> json) => _$GameReviewFromJson(json);

  Map<String, dynamic> toJson() => _$GameReviewToJson(this);
 }

@JsonSerializable()
 class ItemCount {
   int itemType;
   int count;

   ItemCount();

   factory ItemCount.fromJson(Map<String, dynamic> json) => _$ItemCountFromJson(json);

  Map<String, dynamic> toJson() => _$ItemCountToJson(this);
 }

 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();

  factory GameRecord.fromJson(Map<String, dynamic> json) => _$GameRecordFromJson(json);

  Map<String, dynamic> toJson() => _$GameRecordToJson(this);
 }

然后通过从终端运行代码生成实用程序来生成JSON序列化代码:

flutter packages pub run build_runner build

现在您可以使用jsonEncode()和jsonDecode()来存储和检索来自Firestore的对象

用于设置数据:

Firestore.instance
      .collection("games")
      .document("zZJKQOuuoYVgsyhJJAgc")
      .setData(jsonDecode(jsonEncode(gameRecord)));

用于检索数据:

 GameRecord.fromJson(jsonDecode(jsonEncode(snapshot.data)));