List <dynamic>不是List <option>

时间:2019-02-24 10:37:02

标签: firebase dart flutter google-cloud-firestore

我有一个带有questions集合的Cloud Firebase数据库。每个question都有一个地图options的列表。 我正在使用Flutter,并且有questionoption的以下类:

class Question {
  final String text;
  final List<Option> options; // I have tried changing this to List<dynamic> but it doesn't help
  final String reference;

  Question(this.text, this.options, this.reference);

  Question.fromMap(Map<String, dynamic> map, {this.reference}) : 
    text = map['text'],
    options = map['options']; // here the error happens

  Question.fromSnapshot(DocumentSnapshot snapshot)
     : this.fromMap(snapshot.data, reference: snapshot.documentID);
}

option

class Option {
  final String text;
  final int votes;
  bool isSelected;

  Option(this.text, this.votes, this.isSelected);

  Option.fromMap(Map<String, dynamic> map) : 
    text = map['text'],
    votes = map['votes'];
}

我真的不知道该如何解决。但是,这种错误似乎在互联网上无处不在。任何帮助表示赞赏。

更新

供您参考:options是Cloud Firestore中的一组地图。

我根据以下两个答案将代码更改为:

factory Question.fromMap(Map<String, dynamic> map) {

    var options = map['options'];
    var text = map['text'];
    var reference = map['documentID'];
    List<Option> optionsList = options.cast<Option>();

    return new Question(
      text = text,
      options = optionsList,
      reference = reference
    );
  }

  factory Question.fromSnapshot(DocumentSnapshot snapshot) {
    return Question.fromMap(snapshot.data);
  }

仍然出现此错误:type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Option' in type cast

我已经看到并尝试了许多答案,而且所有人似乎都说相同的话。我只是想不通。

Cloud Firestore的屏幕截图:

enter image description here

5 个答案:

答案 0 :(得分:1)

我以前遇到过这个问题,我用

解决了

这是我的代码,您可以将其转换为您的代码:

UserModel.fromSnapshot(DocumentSnapshot snapshot)
      : documentReference = snapshot.reference,
        username = snapshot['username'],
        firstName = snapshot['firstName'],
        lastName = snapshot['lastName'],
        picture = snapshot['picture'],
        routes = Map.from(snapshot['routes']),
        avgScore = snapshot['avgScore'];
}

您在cloud_firestore上的字段类型是什么?

如果它是Map尝试使用Map.from()

如果是List,请尝试使用List.from()

,然后将您的本地字段更改为相同的类型。

答案 1 :(得分:1)

遇到类似问题后,这对我来说非常合适:

class Question {
  final String text;
  final List<Option> options = [];
  final String reference;

  Question(this.text, this.options, this.reference);

  Question.fromMap(Map<String, dynamic> map, {this.reference}){
    text = map['text'];
    if (map['options'] != null) {
      map['options'].forEach((v) {
      options.add(new Option.fromMap(v));
    });
   }
  }

  Question.fromSnapshot(DocumentSnapshot snapshot)
    : this.fromMap(snapshot.data, reference: snapshot.documentID);
}

class Option {
  final String text;
  final int votes;
  bool isSelected;

  Option(this.text, this.votes, this.isSelected);

  Option.fromMap(Map<String, dynamic> map) : 
    text = map['text'],
    votes = map['votes'];
}

答案 2 :(得分:0)

我们正在请求一个列表,但由于我们的应用程序尚无法识别类型,因此我们正在获取一个列表。

要消除此错误,我们必须显式转换动态值。 代替

  Question.fromMap(Map<String, dynamic> map, {this.reference}) : 
  text = map['text'],
  options = map['options']; 

使用

  factory Question.fromMap(Map<String, dynamic> map, {this.reference}) {
   var optionsFromMap  = map['options'];

  //you can use both the steps to check which one will work perfectly for you
  // List<Option> optionsList = new List<Option>.from(optionsFromMap)
   List<Option> optionsList = optionsFromMap.cast<Option>();

  return new Question(
    text = map['text'],
    options = map['options']; 
  );
}

当我想要列表值时,上面的代码可以正常工作

我希望这会对您有所帮助。

答案 3 :(得分:0)

我最终遵循了@chipli onat的建议,并将其与@harsh的答案混合在一起,最终使它起作用。这是我的代码现在的样子:

class Question {
  final String text;
  final String reference;
  final List<Map> options;

  Question(this.text, this.options, this.reference);

  factory Question.fromMap(Map<String, dynamic> map, String reference) {

    var options = map['options'];
    var text = map['text'];
    List<Map> optionsList = options.cast<Map>();

    return new Question(
      text = text,
      options = optionsList,
      reference = reference
    );
  }

  factory Question.fromSnapshot(DocumentSnapshot snapshot) {
    return Question.fromMap(snapshot.data, snapshot.documentID);
  }
}

class Option {
  final String text;
  final int votes;
  bool isSelected;

  Option(this.text, this.votes, this.isSelected);

  Option.fromMap(Map<dynamic, dynamic> map) : // notice Map<dynamic, dynamic> here
    text = map['text'],
    votes = map['votes'];
}

我敢肯定,这个答案可以改善,但是老实说,我不完全理解为什么它必须如此困难。希望这个答案对您有所帮助。

答案 4 :(得分:0)

此代码比建议的解决方案更具可读性。我在项目中使用了它。

var optionsMap = map['options'] as List;
List<Option> optionsList = optionsMap.map((o) => Option.fromMap(o.cast<String, dynamic>())).toList();
class Option {
  final String text;
  final int votes;
  bool isSelected;

  Option(this.text, this.votes, this.isSelected);

  Option.fromMap(Map<dynamic, dynamic> map) : // notice Map<dynamic, dynamic> here
    text = map['text'],
    votes = map['votes'];
}

来源: How to fix this Error: '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'