#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. Поэтому в этом случае вам следует рассмотреть возможность создания отдельного виджета для флажка и перебирать список (возможных ответов), чтобы создать их все, а не создавать каждый отдельно.