我将来自自定义类“PollOption”的数据存储在Firestore中作为 map 数组。当我尝试检索数据时,出现此错误
_InternalLinkedHashMap<String, dynamic> is not a subtype of 'PollOption' in type cast.
我的其他数据很好。

我的模型正在存储到集合中。 PollOption嵌套在此:

class Question{
  //single values
  final Timestamp askedOn;
  final String chosenAnswer;
  final String askedBy;
 ...

  //arrays
  final List<String> categories;
  final List<String> declinedUsers;
  final List<PollOption> pollOptions;
 ...


  Question({
    this.askedBy,
    this.askedByAvatar,
    this.askedByName,

...

    this.pollOptions,
    this.starredMessages,

...

  });

我的PollOption模型:
class PollOption{
  final String option;
  final bool selected;
  final int optionNumber;
  final int votes;

  PollOption({this.option, this.optionNumber, this.selected, this.votes});
}

我如何将数据存储到Firestore:
Future createQuestion(Question data) async {
    ...

    List<Map> sterilizedPolls (){
      List<Map> polls = [];
      if(data.pollOptions != null){
      data.pollOptions.forEach((PollOption pollOption){
        Map option ={
          'option': pollOption.option,
          'votes': pollOption.votes,
          'optionNumber': pollOption.optionNumber,
          'selected': pollOption.selected,
        };
        polls.add(option);
      });

      }
      return polls;

    }


    return await questionCollection.add({
    'askedBy': uid,
...
    'declinedUsers': [],
    'pollOptions': sterilizedPolls(),

...


    });

  }

我如何检索数据:
//Getting all the questions I want
Future<List<Question>> getOpenQuestions() async{
    final QuerySnapshot result = await questionCollection
      .where('locked', isEqualTo: false)
      .where('chosenAnswer', isEqualTo: '')
      .getDocuments();
    final List<DocumentSnapshot> documents = result.documents;
    final List<Question> openQuestions = [];
   documents.forEach((data){
     print('accessing database');
      openQuestions.add(
        Question(
          question: data['question'],

        )
      );
    });

    return openQuestions;
  }

//Creating list from snapshot
List<Question> _questionListFromSnapshot(QuerySnapshot snapshot) {



    return snapshot.documents.map((doc){

      return Question(
        askedBy: doc.data['askedBy'] ?? '',
        askedByName: doc.data['askedByName'] ?? 'Anonymous',

     ...

        pollOptions: List.from(doc.data['pollOptions']).cast<PollOption>() ?? [],

       ...

      );
    }).toList();





  }

//creating stream
   Stream<List<Question>> get openQuestionList {
     try {
      return questionCollection
      .where('locked', isEqualTo: false)
      .snapshots()
      .map(_questionListFromSnapshot);

     } catch (e) {
       return e;
     }

  }

以及我如何显示数据:
class OpenQuestions extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    final openQuestions = Provider.of<List<Question>>(context) ?? [];

    return StreamBuilder<List<Question>>(
        stream: QuestionDatabaseService().openQuestionList,
        builder: (context, snapshot){
          if(snapshot.hasError){
            return Text('Error!');
          }
          if (snapshot.hasData){
              return ListView.builder(
                itemCount: openQuestions.length,
                itemBuilder: (context, index) {
                  return QuestionTile(question: openQuestions[index], context: context);
                },
              );
          }else{
            return Loading();
          }

        }

        );

//The QuestionTile Loaded

class QuestionTile extends StatelessWidget {

  final Question question;
  final context;

  QuestionTile({this.question, this.context});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Card(
        child: ListTile(
         ...
          title: Text(question.question),
          subtitle: question.poll == false ? Text(question.message) : Text('Poll'),
          onTap: (){
            _showBottomModal(context, question);
          },
        ),
      ),

    );
  }
}

//The bottom modal that pops up
void _showBottomModal(context, question)async {
  showModalBottomSheet(context: context, isScrollControlled: true, builder: (context){
    return Container(
      //color: Color(0xFF737373),
      child: Container(
        child: FractionallySizedBox(

//Where the problem widget is being called

          child: AnswerQuestion(question: question),
          heightFactor: 0.90,
          ),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: const Radius.circular(30.0),
            topRight: const Radius.circular(30.0),
          )
        ),

      ),
    );
  });
}

//AnswerQuestion widget where the error is occurring

class _AnswerQuestionState extends State<AnswerQuestion> {

...



  @override
  Widget build(BuildContext context) {



    return Container(

      child:Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
...
          Form(
            key: _formKey,
            child: Column(
              children: [
//Where the data is being displayed with error

                ConstrainedBox(
                constraints: BoxConstraints(
                 maxHeight: 300.0
                 ),
              child: Container(
               child: ListView.builder(
                    itemCount: widget.question.pollOptions.length,
                   itemBuilder: (BuildContext context, int index){



                   return ListTile(
                      title: Text(widget.question.pollOptions[index].option),
                     leading: Radio(
                     value: widget.question.pollOptions[index].optionNumber,
                      groupValue: _optionSelected,
                      onChanged: _handleRadioValueChange,
                   ),
                 );

                ...

抱歉,如果代码太多(或不足),我仍在学习Flutter,并希望提供尽可能多的帮助来解决此错误。

最佳答案

问题出在行:

pollOptions: List.from(doc.data['pollOptions']).cast<PollOption>() ?? [],
doc.data['pollOptions']中的值实际上是JSON数据,在dart中表示为Map<String, dynamic>。 Dart不知道如何将Map自动转换为对象PollOption

考虑一下这个:
pollOptions: doc.data['pollOptions'].map((Map<String, dynamic> json) => PollOption.fromJson(json)).toList()

假设doc.data['pollOptions']返回一个List,如果它是一个JSON数组,则应该这样做。

当然,您需要在fromJson类上使用PollOption工厂构造函数:
class PollOption {
...
   factory PollOption.fromJson(final Map<String, dynamic> json) {
      return PollOption(json["optionkey"], etc);
   }
...
}

09-18 17:46