首页 > 解决方案 > 首次运行消费者抛出错误

问题描述

我有一个从 sqlite 数据库中获得答案的提供者。

import 'package:flutter/material.dart';
import '../models/answer.dart';
import '../helpers/answer_db_helper.dart';

class Answers with ChangeNotifier {
  List<Answer> _answers = [];
  bool newAnswer;
  Answer _answer;

  Answer get selectedAnswer {
    return _answer;
  }

  List<Answer> get answers {
    return _answers;
  }

  Future<void> fetchSelectedAnswer(reportId, questionId) async {
    AnswerDBHelper answerDBHelper = AnswerDBHelper();
    _answers = await answerDBHelper.getAnswerByReportIdAndQuestionId(
        reportId, questionId);
    if (_answers.length == 0) {
      newAnswer = true;
      _answer = new Answer();
    } else {
      newAnswer = false;
      _answer = _answers[0];
    }
    notifyListeners();
  }

  setAnswer(type) {
    _answer.remedialType = type;
    notifyListeners();
  }

  setComment(text) {
    _answer.comment = text;
    notifyListeners();
  }
}

我通过 didChangeDependancies() 我的 AnswerScreen

@override
  void didChangeDependencies() async {
    if (!_dataLoaded) {
      final routeArgs =
          ModalRoute.of(context).settings.arguments as Map<String, Object>;
      sectionName = routeArgs['sectionName'];
      questionId = routeArgs['id'];
      reportId = routeArgs['reportId'];
      selectedQuestion = routeArgs['selectedQuestion'];
      await Provider.of<Answers>(context, listen: false)
          .fetchSelectedAnswer(reportId, questionId);
    }
    _dataLoaded = true;
    super.didChangeDependencies();
  }

我检查答案并使用数据库中的答案更新提供程序中的 _answer 值,或者创建一个新的空白答案,如果它不存在,则仅设置 remedialType 。

class Answer {
  int id;
  int reportId;
  int questionId;
  String remedialType;
  String comment;
  String pictureFilename;
  String pictureUrl;

  Answer({
    this.id,
    this.reportId,
    this.questionId,
    this.remedialType = "Do Not Include",
    this.comment,
    this.pictureFilename,
    this.pictureUrl,
  });

  Map<String, dynamic> toMap() {
    var map = <String, dynamic>{
      'id': id,
      'report_id': reportId,
      'question_id': questionId,
      'remedial_type': remedialType,
      'comment': comment,
      'picture_filename': pictureFilename,
      'picture_url': pictureUrl,
    };
    return map;
  }

  Answer.fromMap(Map<String, dynamic> map) {
    id = map['ID'];
    reportId = map['REPORT_ID'];
    questionId = map['QUESTION_ID'];
    remedialType = map['REMEDIAL_TYPE'];
    comment = map['COMMENT'];
    pictureFilename = map['PICTURE_FILENAME'];
    pictureUrl = map['PICTURE_URL'];
  }
}

在里面的一个小部件中

Consumer<Answers>(builder: (context, answerData, child)

我检查 answerData.selectedAnswer.remedialType 值

Checkbox(
  value:
    (answerData.selectedAnswer.remedialType ==                                     
     "Do Not Include")
       ? true
       : false,
  checkColor: Colors.white,
  activeColor: Colors.purple[600],
  onChanged: (value) {
  if (value == true) {
    setState(() {
     answerData.setAnswer("Do Not Include");
     });
    }
  },
)

这是针对四个单独的复选框小部件完成的。

一切正常,但在第一次运行时,当我选择第一个问题并且 AnswerScreen 加载了所有正确的数据但我在调试控制台中收到此错误。

The following NoSuchMethodError was thrown building Consumer<Answers>(dirty, dependencies: [_InheritedProviderScope<Answers>]):
The getter 'remedialType' was called on null.
Receiver: null
Tried calling: remedialType
The relevant error-causing widget was
Consumer<Answers>
package:inspect/screens/answer_screen.dart:60
When the exception was thrown, this was the stack
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      _AnswerScreenState.build.<anonymous closure>
package:inspect/screens/answer_screen.dart:101
#2      Consumer.buildWithChild
package:provider/src/consumer.dart:175
#3      SingleChildStatelessWidget.build
package:nested/nested.dart:260
#4      StatelessElement.build
package:flutter/…/widgets/framework.dart:4701
...

似乎直到检查之后才在提供程序中设置 answerData.selectedAnswer 值。

随后的答案选择按预期工作,启用了正确的复选框并且没有错误。

我只使用 Flutter 大约 3 周,所以我是新手,但谁能帮我解决这个问题?

提前致谢

标签: flutterdart

解决方案


是的,正如您所提到的,问题在于_answer( selectedAnswer) 的值在有人第一次选择复选框之前为空。

您应该在Checkbox小部件的value属性中添加一个检查,以查看是否selectedAnswernull,如果是则返回 false。

value:
    (answerData.selectedAnswer!=null && answerData.selectedAnswer.remedialType ==                                     
     "Do Not Include")
       ? true
       : false

false如果selectedAnswer是_null


推荐阅读