Flutter/Dart 从 Firestore 投射到地图中

Posted

技术标签:

【中文标题】Flutter/Dart 从 Firestore 投射到地图中【英文标题】:Flutter/Dart casting from Firestore into map 【发布时间】:2020-03-08 07:31:46 【问题描述】:

我在将数据从 firestore 映射到模型时遇到问题。 我已经尝试了几个小时并且总是遇到像 'Map can't be cast to Map' 或 'type '_InternalLinkedHashMap' 不是类型'Map'的子类型之类的转换错误(异常) '

我尝试了这些链接中的示例:

How do you load array and object from Cloud Firestore in Flutter

https://github.com/dart-lang/sdk/issues/36836

还有很多,仍然不明白这东西是如何工作的。

这是我的实体和模型类:

实体

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';

class ScreenHomeEntity extends Equatable 
  final String id;
  final String userName;
  final String userEmail;
  final String mainDoor;
  final Map<dynamic, dynamic> doors;

  const ScreenHomeEntity(
      this.id, this.userName, this.userEmail, this.mainDoor, this.doors);

  @override
  List<Object> get props => [id, userName, userEmail, mainDoor, doors];

  @override
  String toString() =>
      'ScreenHomeEntity id: $id, userName: $userName, userEmail: $userEmail, mainDoor: $mainDoor, doors: $doors';

  Map<String, Object> toJson() 
    return 
      'id': id,
      'userName': userName,
      'userEmail': userEmail,
      'mainDoor': mainDoor,
      'doors': doors,
    ;
  

  static ScreenHomeEntity fromJson(Map<String, Object> json) 
    return ScreenHomeEntity(
      json['id'] as String,
      json['userName'] as String,
      json['userEmail'] as String,
      json['mainDoor'] as String,
      json['doors'] as Map<dynamic, dynamic>,
    );
  

  Map<String, Object> toDocument() 
    return 
      'userName': userName,
      'userEmail': userEmail,
      'mainDoor': mainDoor,
      'doors': doors,
    ;
  

  static ScreenHomeEntity fromDocument(DocumentSnapshot doc) 
    return ScreenHomeEntity(
      doc.documentID,
      doc.data['userName'],
      doc.data['userEmail'],
      doc.data['mainDoor'],
      doc.data['doors'],
    );
  

型号:

import 'package:brava_flutter/data/entities/screen_home_entity.dart';
import 'package:meta/meta.dart';

@immutable
class ScreenHome 
  final String id;
  final String userName;
  final String userEmail;
  final String mainDoor;
  final Map<String, ScreenHomeDoor> doors;

  ScreenHome(this.userName,
      String userEmail = '',
      String id,
      String mainDoor,
      Map<String, ScreenHomeDoor> doors)
      : this.userEmail = userEmail ?? '',
        this.id = id,
        this.mainDoor = mainDoor ?? '',
        this.doors = doors ?? Map<String, ScreenHomeDoor>();

  ScreenHome copyWith(
    String id,
    String userName,
    String userEmail,
    String mainDoor,
    Map<String, ScreenHomeDoor> doors,
  ) 
    return ScreenHome(
      userName ?? this.userName,
      id: id ?? this.id,
      userEmail: userEmail ?? this.userEmail,
      mainDoor: mainDoor ?? this.mainDoor,
      doors: doors ?? this.doors,
    );
  

  @override
  int get hashCode =>
      id.hashCode ^
      userName.hashCode ^
      userEmail.hashCode ^
      mainDoor.hashCode ^
      doors.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ScreenHome &&
          runtimeType == other.runtimeType &&
          id == other.id &&
          userName == other.userName &&
          userEmail == other.userEmail &&
          mainDoor == other.mainDoor &&
          doors == other.doors;

  @override
  String toString() =>
      'ScreenHomeModel id: $id, userName: $userName, userEmail: $userEmail, mainDoor: $mainDoor, doors: $doors';

  ScreenHomeEntity toEntity() =>
      ScreenHomeEntity(id, userName, userEmail, mainDoor, doors);

  static ScreenHome fromEntity(ScreenHomeEntity entity) 
    return ScreenHome(
      entity.userName,
      id: entity.id,
      userEmail: entity.userEmail,
      mainDoor: entity.mainDoor,
      doors: entity.doors, // EXCEPTION
    );
  


class ScreenHomeDoor 
  String name;
  String address;

  ScreenHomeDoor.fromMap(Map<dynamic, dynamic> data)
      : name = data['name'],
        address = data['address'];

firestore 数据示例:

【问题讨论】:

您遗漏了一些代码,但我发现可能存在类型不兼容的错误。你没有忘记使用你的ScreenHomeDoor.fromMap(Map&lt;dynamic, dynamic&gt; data) 方法吗?您可以从 Firebase 控制台显示您的 Firestore 对象结构吗?如果我了解您打算如何将您的 Map&lt;dynamic, dynamic&gt; 转换为 Map&lt;String, ScreenHomeDoor&gt;,我可以为您提供帮助 我从 Firestore 添加了图片(数据结构)。我没有忘记调用 .fromMap (ScreenHomeDoor),我在模型类中用 'fromEntity' 调用它,这就是我得到错误的地方。 【参考方案1】:

答案:

在模型中,方法“fromEntity”我没有将实体映射(动态)转换为模型映射(对象),而这正是发生异常的地方。 这个动态映射中的每个“值”都应该被转换为对象,我一直都做错了。

  static ScreenHome fromEntity(ScreenHomeEntity entity) 
    return ScreenHome(
      entity.userName,
      id: entity.id,
      userEmail: entity.userEmail,
      mainDoor: entity.mainDoor,
      doors: entity.doors
          .map((k, v) => MapEntry(k as String, ScreenHomeDoor.fromMap(v))),
    );
  

一直以来我都在尝试使用MapEntry(k as String, v as ScreenHomeDoor.fromMap(v))

一个简单而愚蠢的错误......

【讨论】:

以上是关于Flutter/Dart 从 Firestore 投射到地图中的主要内容,如果未能解决你的问题,请参考以下文章

查询时如何在 Flutter (Dart) 中使用变量 Cloud Firestore

如何在简单的flutter-dart代码中使用对象snapshot.data实现空安全?

如何使用颤振删除 Firestore 文档中的字段

Flutter/Dart - 调用一个 Future<String> ...但只需要返回一个 String 的函数

在 Flutter 中显示两个 Firestore 时间戳值之间的差异

我该如何解决这个问题:Android Studio - Flutter - Dart - firebase [关闭]