List<dynamic> is not a subtype of List<Option>

五迷三道 提交于 2020-12-13 03:21:04

问题


I have a Cloud Firebase database with a questions collection. Each question has a list of map options. I'm using Flutter and have the following classes for question and option:

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

and 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'];
}

I really have no idea how I can fix this. This kind of error seems to be everywhere on the internet, though. Any help is appreciated.

Update

For your information: options is an array of map in Cloud Firestore.

I changed my code based on the two answers below to:

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

Still, I get this error: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Option' in type cast

I have seen and tried so many answers and all seem to say the same. I just can't figure this out.

Screenshot of Cloud Firestore:


回答1:


I've met with this problem before, I solved with

this is my code you can convert it to yours:

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'];
}

what your field type on cloud_firestore ?

if its a Map try to use Map.from()

if it's a List try to use List.from()

and change your local field the same type.




回答2:


This code is more readable than your suggested solution. I used it in my project.

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'];
}

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




回答3:


After encountering similar issues this worked perfectly for me:

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'];
}



回答4:


We are requesting a List but we are getting a List because our application cannot identify the type yet.

To remove this error, we have to explicitly cast the dynamic value. In place of

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

use

  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']; 
  );
}

the above code is working perfectly when I want List value

I hope this will help you.




回答5:


I ended up following @chipli onat advice and mix it with @harsh answer and finally got it to work. This is how my code looks like now:

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

and

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'];
}

I'm sure this answer could be improved, but to be honest I don't understand entirely why it has to be so difficult. I hope this answer helps you.



来源:https://stackoverflow.com/questions/54851001/listdynamic-is-not-a-subtype-of-listoption

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!