Is it true that a stateful widget has to be updated/rebuild by itself and if the parent widget updates, it should also update right ?
What are the solutions for that.
I want to implement a quiz app. it has playquiz widget shows viewquiz or resultpage depending on question index which are all fetched using provider.
viewquiz has question text and answeroptions(stateful widget). When I click answer it notifies all consumers. I can use setstate to change color but when next question comes the color stays the same if i change color to blue then it stays blue. for now the solution is to use timer for that and reset back again using setstate.
Code
Here is my solution. If someone can help me imporve it. i feel like this is not the best way to do it.
quizmodel.dart
class QuizModel extends ChangeNotifier {
var questions;
QuizModel(this.questions);
var qindex = 0;
var score = 0;
void check(ans) {
if (ans) {
score = score + 1;
}
qindex = qindex + 1;
notifyListeners();
}
}
playquiz.dart
return ChangeNotifierProvider<QuizModel>(
create: (context) => QuizModel(snapshot.data),
child: Scaffold(
//appBar: AppBar(title: Text("nice app")),
body: Consumer<QuizModel>(builder: (context, QuizModel, child) {
if (QuizModel.questions.length == 0) {
return Center(
child: Text("Loading..."),
);
} else {
print(snapshot.data);
// return Text("Ok");
return QuizModel.qindex < QuizModel.questions.length
? ViewQuiz(QuizModel.questions, QuizModel.qindex)
: ViewResult(QuizModel.score);
}
}),
),
);
answer.dart
class Answer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final qzm = Provider.of<QuizModel>(context, listen: false);
//var ptions = widget.options;
return Column(
children: (qzm.questions[qzm.qindex]["qoptions"] as List<dynamic>)
.map((opt) => AnswerOption(qzm, opt))
.toList(),
);
}
}
class AnswerOption extends StatefulWidget {
var qzm;
var opt;
AnswerOption(this.qzm, this.opt);
@override
_AnswerOptionState createState() => _AnswerOptionState();
}
var colordata = Colors.white;
class _AnswerOptionState extends State<AnswerOption> {
_checker(ans) {
// print(idx);
if (widget.qzm.questions[widget.qzm.qindex]["answer"] == ans) {
print("nice");
setState(() {
colordata = Colors.green;
});
Timer(
Duration(milliseconds: 500),
() => {
setState(() {
colordata = Colors.white;
}),
widget.qzm.check(true),
});
} else {
setState(() {
colordata = Colors.red;
});
Timer(
Duration(milliseconds: 1000),
() => {
setState(() {
colordata = Colors.white;
}),
widget.qzm.check(false),
});
}
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: 250,
child: RaisedButton(
onPressed: () => _checker(widget.opt),
child: Text(
widget.opt,
style: TextStyle(fontSize: 15, color: Colors.black),
),
color: colordata
// duration: Duration(milliseconds: 300),
),
);
}
}
full code :