I built a simple quiz app with 3 questions, the logic works and it takes you through all the questions. At the end there is an alert dialog that pops up and shows you your score, after clicking close it resets the quiz and allows you to play again.
I am now getting an error when the alert dialog pops up that says
RangeError (index): Invalid value: Not in inclusive range 0..2 3
Please help with this.
Here is my code for the app
import 'package:flutter/material.dart';
void main() => runApp(const QuizApp());
class QuizApp extends StatelessWidget {
const QuizApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Quiz Game',
home: QuizPage(),
);
}
}
class QuizPage extends StatefulWidget {
const QuizPage({super.key});
@override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
int _currentQuestion = 0;
int _score = 0;
final List<Map<String, Object>> _questions = [
{
'question': 'What is the capital of France?',
'answers': [
{'text': 'Paris', 'correct': true},
{'text': 'London', 'correct': false},
{'text': 'Berlin', 'correct': false},
],
},
{
'question': 'Is this app useful?',
'answers': [
{'text': 'Yes', 'correct': true},
{'text': 'No', 'correct': false},
],
},
{
'question': 'Is this app fun?',
'answers': [
{'text': 'Yes', 'correct': true},
{'text': 'No', 'correct': false},
{'text': 'Maybe', 'correct': false},
],
},
];
@override
Widget build(BuildContext context) {
// Get the current question and answers
final Map<String, Object> currentQuestion = _questions[_currentQuestion];
final String question = currentQuestion['question'] as String;
final List<Map<String, Object>> answers =
currentQuestion['answers'] as List<Map<String, Object>>;
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Display the current question
Text(
question,
style: Theme.of(context).textTheme.headline3,
),
const SizedBox(height: 20),
// Display the answer buttons
...answers.map((Map<String, Object> answer) {
return TextButton(
child: Text(answer['text'] as String),
onPressed: () => _answerQuestion(answer['correct'] as bool),
);
}),
],
),
),
);
}
void _answerQuestion(bool isCorrect) {
if (isCorrect) {
_score++;
}
setState(() {
_currentQuestion++;
// Check if we have reached the end of the quiz
if (_currentQuestion >= _questions.length) {
// Show a dialog with the final score
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Quiz Finished'),
content: Text('You scored $_score points'),
actions: [
TextButton(
child: const Text('Close'),
onPressed: () {
// Reset the quiz
setState(() {
_currentQuestion = 0;
_score = 0;
});
Navigator.of(context).pop();
},
),
],
);
},
);
}
});
}
}
2
Answers
In this case, the error is because
_currentQuestion
is incremented in setState. Changing its value insetState
will causebuild
to run again with the new value. This means that the expression_questions[_currentQuestion]
will be evaluated. Since_questions
is a List with 3 objects, the valid values for_currentQuestion
are 0, 1, or 2. Once you increment_currentQuestion
to 3, that is out of the range of valid values. So Dart responds with the error you are seeing.Try moving your increment logic out of setState, and only call setState if
_currentQuestion
has a valid value.I’ve changed your
_answerQuestion
function a bit. I think is a good idea toawait showDialog
since it is aasync
call. Then removed unnecessarysetState
calls. Root of the problem was explained by@pmich16
and I just did the coding.