1
votes

La liste n'est pas un sous-type de la liste

J'ai une base de données Cloud Firebase avec une collection de questions . Chaque question a une liste des options de la carte. J'utilise Flutter et j'ai les classes suivantes pour question et option:

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

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

Je ne sais vraiment pas comment je peux résoudre ce problème. Ce genre d'erreur semble cependant être partout sur Internet. Toute aide est appréciée.

Pour votre information: options est un tableau de cartes dans Cloud Firestore.

J'ai changé mon code en fonction des deux réponses ci-dessous en:

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

Pourtant, j'obtiens cette erreur: type '_InternalLinkedHashMap ' n'est pas un sous-type de type 'Option' dans le type cast

J'ai vu et essayé tant de réponses et toutes semblent dire la même chose. Je ne peux tout simplement pas comprendre cela.

Capture d'écran de Cloud Firestore:

entrez la description de l'image ici


0 commentaires

5 Réponses :


5
votes

J'ai déjà rencontré ce problème, j'ai résolu avec

ceci est mon code, vous pouvez le convertir en le vôtre:

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

ce que votre champ type sur cloud_firestore ?

s'il s'agit d'une carte , essayez d'utiliser Map.from()

si c'est une liste code > essayez d'utiliser List.from ()

et changez votre champ local du même type.


9 commentaires

options est un tableau de cartes dans Cloud Firestore.


Votre solution ne fonctionne pas pour moi, j'obtiens cette erreur: type '_InternalLinkedHashMap ' n'est pas un sous-type de type 'Option'


J'ai essayé List.from () , btw, car cela a du sens, mais j'obtiens l'erreur ci-dessus. Je sais que cette réponse devrait fonctionner, mais ce n'est pas le cas.


Pouvez-vous publier une photo d'un document associé à partir de cloud firestore?


J'ai posté une capture d'écran. Voici à quoi cela ressemble en gros: options: [{text: "some text", votes: 0}]


Des idées? Je commence à être désespéré. Le problème est que je ne peux pas vraiment utiliser un autre type de structure, car c'est la meilleure pour mon cas d'utilisation.


Je regarde mais au lieu de créer une liste d'objets Option: List vous devriez créer une liste d'options Maps List ; et vous devriez être capable d'obtenir de Firestore, alors vous devez remplir vos objets Option à partir de cette liste de cartes.


Je l'ai enfin fait fonctionner en utilisant votre dernière suggestion! Merci!


Si cela vous est utile, pouvez-vous faire accepter la réponse et voter pour? _? @Loolooii



0
votes

Nous demandons une liste mais nous obtenons une liste car notre application ne peut pas encore identifier le type.

Pour supprimer cette erreur, nous devons convertir explicitement la valeur dynamique. À la place de

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

use

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

le code ci-dessus fonctionne parfaitement quand je veux la valeur de liste

J'espère que cela vous aidera.


1 commentaires

Je ne peux pas passer {this.reference} à la méthode d'usine. Aussi, que dois-je faire maintenant avec fromSnapshot ? J'obtiens: Le constructeur génératif ne peut pas rediriger vers un constructeur d'usine



0
votes

J'ai fini par suivre les conseils de @chipli onat et je les ai mélangés avec la réponse @harsh et je l'ai finalement fait fonctionner. Voici à quoi ressemble mon code maintenant:

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

et

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

Je suis sûr que cette réponse pourrait être améliorée, mais pour être honnête Je ne comprends pas tout à fait pourquoi cela doit être si difficile. J'espère que cette réponse vous aidera.


0 commentaires

1
votes

Ce code est plus lisible que la solution suggérée. Je l'ai utilisé dans mon projet.

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'];
}
var optionsMap = map['options'] as List;
List<Option> optionsList = optionsMap.map((o) => Option.fromMap(o.cast<String, dynamic>())).toList();

Source: Comment corriger cette erreur: '_InternalLinkedHashMap 'n'est pas un sous-type de type' Map '


0 commentaires

1
votes

Après avoir rencontré des problèmes similaires, cela a parfaitement fonctionné pour moi:

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


0 commentaires