При первом запуске потребитель выдает ошибку

#flutter #dart

#флаттер #dart

Вопрос:

У меня есть поставщик, который получает ответ из базы данных 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()

 @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 в поставщике с ответом в БД или создаю новый пустой ответ, содержащий только набор исправлений, если он не существует.

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

Это делается для четырех отдельных виджетов флажков.

Все работает нормально, но при первом запуске, когда я выбираю первый вопрос, и экран ответов загружается со всеми правильными данными, но я получаю эту ошибку в консоли отладки.

 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 недель, поэтому я новичок, но кто-нибудь может помочь мне решить эту проблему?

Заранее спасибо

Ответ №1:

Ну, значение _answer равно null при создании экземпляра Answers , поэтому selectedAnswer также будет null, пока базовой переменной не будет присвоено значение. Вы должны присвоить начальное значение с помощью конструктора, например:

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

  Answers(this._answer); 
  /* etc... */
}
  

Затем Answers создайте экземпляр, передавая начальное значение для _answer .

Ответ №2:

Да, как вы упомянули, проблема в том, что значение _answer ( selectedAnswer ) равно нулю до тех пор, пока кто-то не установит флажок в первый раз.

Вы должны добавить проверку внутри свойства Checkbox виджета value , чтобы увидеть, есть ли selectedAnswer null значение, и вернуть false, если оно есть.

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

Это установит значение false selectedAnswer , равное, если null

Комментарии:

1. Спасибо. Это работает, но мне пришлось добавить проверку в 5 разных местах.

2. Поэтому в этом случае вам следует рассмотреть возможность создания отдельного виджета для флажка и перебирать список (возможных ответов), чтобы создать их все, а не создавать каждый отдельно.