Error with displaying message after quiz ends , flutter - flutter

Image
There are 3 questions in my app currently and as per my code after all my questions are answered one by one, a widget should appear on the screen which completely fills the screen and which should say " You did it". But unfortunately, I have been trying a lot and still can't find solution.
below is code for main.dart
import 'package:flutter/material.dart';
import './quiz.dart';
import './result.dart';
//void main(){
//runApp(MyApp());
//}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _questions = const [
{
'questionText': 'What\'s is your favourite color? ',
'answers': ['Black', 'Red', 'Green', 'white'],
},
{
'questionText': 'What\'s is your favourite animal?',
'answers': ['Snake', 'Elephant', 'Lion'],
},
{
'questionText': 'Who is your favourite instructor? ',
'answers': ['Max', 'Max', 'Max', 'Max'],
},
];
var _questionIndex = 0;
void _answerQuestion() {
// var aBool= true;
// aBool = false;
setState(() {
_questionIndex = _questionIndex;
});
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more questions!');
} else {
print('No more questions!');
}
}
#override
Widget build(BuildContext context) {
// var dummy = ['Hello'];
// dummy.add('Max');
// print(dummy);
// dummy = [];
// questions = [];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body : _questionIndex <= 2
? Quiz(
answerQuestion: _answerQuestion,
questionIndex: _questionIndex,
questions: _questions,
)
: Result(),
),
);
}
}
below is code for question.dart
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Text(
questionText,
style: TextStyle(fontSize: 28),
textAlign: TextAlign.center,
),
);
}
}`
below id code for answer.dart
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final Function selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
child: Text(answerText),
onPressed: selectHandler,
),
);
}
}
below is code for quiz.dart
import 'package:flutter/material.dart';
import './question.dart';
import './answer.dart';
class Quiz extends StatelessWidget {
final List<Map<String, Object>>questions;
final int questionIndex;
final Function answerQuestion;
Quiz({
#required this.questions,
#required this.answerQuestion,
#required this.questionIndex,
});
Widget build(BuildContext context) {
return Column(
children: [
Question(
questions[questionIndex]['questionText'],
),
...(questions[questionIndex]['answers'] as List<String>)
.map((answer) {
return Answer(answerQuestion, answer);
}).toList()
],
);
}
}
below is code for result.dart
import 'package:flutter/material.dart';
class Result extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('You did it!'),
);
}
}

The moment I fixed the following line, your app started working as you described. Going through each question and then showing the "You did it!" text.
setState(() {
_questionIndex++;
});
You were just doing _questionIndex = _questionIndex before, which doesn't change any value.

I am not getting the error you mentioned,
Here what I did,
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _questions = const [
{
'questionText': 'What\'s is your favourite color? ',
'answers': ['Black', 'Red', 'Green', 'white'],
},
{
'questionText': 'What\'s is your favourite animal?',
'answers': ['Snake', 'Elephant', 'Lion'],
},
{
'questionText': 'Who is your favourite instructor? ',
'answers': ['Max', 'Max', 'Max', 'Max'],
},
];
var _questionIndex = 0;
void _answerQuestion(String question, String selectedAnswer) {
print("==============================================");
print("QUESTION: $question");
print("SELECTED ANSWER: $selectedAnswer");
print("==============================================");
setState(() {
_questionIndex++;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: _questionIndex < _questions.length //TODO:
? Quiz(
quizQuestion: _questions[_questionIndex]["questionText"],
quizOptions: _questions[_questionIndex]["answers"],
onAnswerSelect: _answerQuestion,
)
: Result(),
),
);
}
}
class Quiz extends StatelessWidget {
final String quizQuestion;
final List<String> quizOptions;
final void Function(String, String) onAnswerSelect;
Quiz({
#required this.quizQuestion,
#required this.quizOptions,
#required this.onAnswerSelect,
});
Widget build(BuildContext context) {
return Column(
children: [
Question(quizQuestion),
...quizOptions.map(
(option) => Answer(
answerText: option,
selectHandler: () => onAnswerSelect(quizQuestion, option),
),
),
],
);
}
}
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Text(
questionText,
style: TextStyle(fontSize: 28),
textAlign: TextAlign.center,
),
);
}
}
class Answer extends StatelessWidget {
final String answerText;
final VoidCallback selectHandler;
Answer({this.answerText, this.selectHandler});
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
child: Text(answerText),
onPressed: selectHandler,
),
);
}
}
class Result extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('You did it!'),
);
}
}

Related

The method 'map' was called on null

I have a got a problem with the null, I have no idea why.. I'm begginer in the flutter
The method 'map' was called on null.
Receiver: null
Tried calling: map(Closure: (String) => Answer)"
main.dart
import 'package:flutter/material.dart';
import './question.dart';
import './answer.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
static const questions = [
{
'questionText': 'Whats your favourite car?',
'answers': ['HYUNDAI', 'BMW', 'KIA', 'AUDI']
},
{
'questionText': 'What is your favourite game?',
'answers': ['CS:GO', 'LOL', 'WOW', 'GTA']
},
{
'questionText': 'What is your favourite phone?',
'answer': ['IPHONE', 'SAMSUNG', 'SONY', 'HUAWEI']
}
];
var _questionIndex = 0;
void _answerQuestion() {
setState(() {
_questionIndex = _questionIndex + 1;
});
if (_questionIndex < questions.length) {
print('We have more questions');
}
print(_questionIndex);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text('Quiz App'),
),
body: _questionIndex < questions.length
? Column(
children: [
Question(
questions[_questionIndex]['questionText'] as String,
),
...(questions[_questionIndex]['answers'] as List<String>)
.map((answer) {
return Answer(_answerQuestion, answer);
}).toList(),
],
)
: Center(child: Text('We finally got it'))),
);
}
}
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Text(
questionText,
style: TextStyle(fontSize: 22),
textAlign: TextAlign.center,
),
);
}
}
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final VoidCallback selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: selectHandler,
child: Text(answerText),
));
}
}
enter image description here
Please help me :)
I looked up on a different topics about this, adding ?? to toList () , but still the same error
static const questions = [
{
'questionText': 'Whats your favourite car?',
'answers': ['HYUNDAI', 'BMW', 'KIA', 'AUDI']
},
{
'questionText': 'What is your favourite game?',
'answers': ['CS:GO', 'LOL', 'WOW', 'GTA']
},
{
'questionText': 'What is your favourite phone?',
'answer': ['IPHONE', 'SAMSUNG', 'SONY', 'HUAWEI']
}
];
In the last item, you write answer instead of answers.
Please have a look!

setState() or markNeedsBuild() called during build, widget was currently being built when offending call was made

I am trying to make a simple quiz app using flutter but this has been bugging me for over a day now
The error mainly states that the myApp was called during the build of Quiz. I have no idea what to do even I have searched on youtube too.
Error message
Main.dart code:
import 'package:first/result.dart';
import 'package:flutter/material.dart';
import './quiz.dart';
import './result.dart';
void main(List<String> args) => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _questions = [
{
'questionText': 'What\'s your favorite colour?',
'answers': ['Black', 'Red', 'Blue', 'Green'],
},
{
'questionText': 'What\'s your favorite animal?',
'answers': ['Cat', 'Dog', 'Pig', 'Parrot'],
},
{
'questionText': 'Who\'s your favorite wrestler?',
'answers': ['Seth Rollins', 'Roman Reigns', 'John Cena', 'Randy Orton'],
},
];
var _questionIndex = 0;
void _answerQuestion() {
setState(() {});
_questionIndex = _questionIndex + 1;
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: _questionIndex < _questions.length
? Quiz(
answerQuestion: _answerQuestion,
questionIndex: _questionIndex,
questions: _questions)
: Result(),
),
);
}
}
quiz.dart code:
import './question.dart';
import './answer.dart';
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final Function answerQuestion;
Quiz({required this.questions, required this.answerQuestion, required this.questionIndex});
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion(), answer);
}).toList()
],
);
}
}
result.dart code:
import 'package:flutter/material.dart';
class Result extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('All questions are answered !!'),
);
}
}
answer.dart code:
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final VoidCallback selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
#override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: selectHandler,
child: Text(answerText)),
);
}
}
question.dart code:
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10.0),
child: Text(questionText,
style: TextStyle(fontSize: 28), textAlign: TextAlign.center),
);
}
}
Help please.
The reason you are getting the error message is that you are calling setState every time the build method of the MyApp widget is called. The setState method will re-trigger the build of the widget, and then setState is called again. So basically you have an infinite re-render.
If you look at your code in quiz.dart we find the reason for this infinite re-render:
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion() /*<-- here is the problem*/, answer);
}).toList()
],
);
}
Every time the quiz widget calls it build method, it will call the answerQuestion method, which will call the build method of your main widget, which in turn will rebuild the quiz widget. Instead of calling the method here, you should send this callback method further down the three to the answer widget:
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final Function answerQuestion;
Quiz({required this.questions, required this.answerQuestion, required this.questionIndex});
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion /* Notice the difference */, answer);
}).toList()
],
);
}
}
class Answer extends StatelessWidget {
final Function answerQuestion; // I renamed this to answerQuestion, feel free to stick with selectHandler
final String answerText;
Answer(this.answerQuestion, this.answerText);
#override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: answerQuestion,
child: Text(answerText)),
);
}
}
I also would advise you to update the logic in your answerQuestion method widget, so you wrap your setState method around the state update you are doing:
void _answerQuestion() {
setState(() {
_questionIndex = _questionIndex + 1;
});
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
The main issue occurs on Answer and Quiz widget while using Function.
Use VoidCallback on Quiz instead of Funtion.
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final VoidCallback answerQuestion;
const Quiz({
Key? key,
required this.questions,
required this.answerQuestion,
required this.questionIndex,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map(
(answer) {
return Answer(answerQuestion, answer);
},
).toList()
],
);
}
}
Full snippet
import 'package:flutter/material.dart';
void main(List<String> args) => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _questions = [
{
'questionText': 'What\'s your favorite colour?',
'answers': ['Black', 'Red', 'Blue', 'Green'],
},
{
'questionText': 'What\'s your favorite animal?',
'answers': ['Cat', 'Dog', 'Pig', 'Parrot'],
},
{
'questionText': 'Who\'s your favorite wrestler?',
'answers': ['Seth Rollins', 'Roman Reigns', 'John Cena', 'Randy Orton'],
},
];
var _questionIndex = 0;
void _answerQuestion() {
setState(() {});
_questionIndex = _questionIndex + 1;
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: _questionIndex < _questions.length
? Quiz(
answerQuestion: _answerQuestion,
questionIndex: _questionIndex,
questions: _questions)
: Result(),
),
);
}
}
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final VoidCallback answerQuestion;
const Quiz({
Key? key,
required this.questions,
required this.answerQuestion,
required this.questionIndex,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map(
(answer) {
return Answer(answerQuestion, answer);
},
).toList()
],
);
}
}
class Answer extends StatelessWidget {
final VoidCallback selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
#override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: selectHandler,
child: Text(answerText),
),
);
}
}
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10.0),
child: Text(questionText,
style: TextStyle(fontSize: 28), textAlign: TextAlign.center),
);
}
}
class Result extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('All questions are answered !!'),
);
}
}
As per the code you provided, it seems you are only passing instances of the functions as in _answerQuestion in your main.dart code and further into other files. As per my experience of working with dart and flutter, it is highly recommended that when one is passing a function, to a widget, one should always pass it in the following manner:
Quiz(
answerQuestion: () => _answerQuestion(), // pass it like this to avoid errors.
questionIndex: _questionIndex,
questions: _questions)
That is, you should pass it as a lambda/Anonymous function. i.e.
void yourFunction() {
// You do something here
}
AnyWidget(
onPressed: () => yourFunction();, // This is called a lambda/anonymous function.
);
The reason for this is that the function when passed like this onPressed: yourFunction, would get called even when user hasn't actually interacted with the app, i.e. it gets called when building the widget. To avoid that, we use lambda functions.
If my answer was helpful, please mark my answer as Correct. Thank you!
Error is showing in Quiz ..(questions[questionIndex]['answers'] as ..

The argument type 'Function' can't be assigned to the parameter type 'void Function()?

I am getting this error on answer.dart
"lib/answer.dart:15:20: Error: The argument type 'Function' can't be assigned to the parameter type 'void Function()?'."
Here are the files:
main.dart
import 'package:flutter/material.dart';
import 'Questions.dart';
import 'answer.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
// ignore: dead_code
throw UnimplementedError();
}
}
class _MyAppState extends State<MyApp> {
var _questionIndex = 0;
var questions = [
'what\'s your fav color?',
'what\'s your fav Food?',
'what\'s your fav Animal?'
];
void _answerQuestion() {
setState(() {
_questionIndex++;
if (_questionIndex >= questions.length) _questionIndex = 0;
});
print(_questionIndex);
print(questions.length);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter App'),
),
body: Column(
children: [
Question(questions[_questionIndex]),
Answer(_answerQuestion),
Answer(_answerQuestion),
Answer(_answerQuestion),
],
),
),
);
}
}
answer.dart
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final Function selectHandler;
Answer(this.selectHandler);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: ElevatedButton(
child: Text('Ans 1'),
onPressed: selectHandler,
style: ElevatedButton.styleFrom(
primary: Colors.red,
),
),
);
}
}
Questions.dart
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
child: Text(
questionText,
style: TextStyle(fontSize: 28),
textAlign: TextAlign.center,
),
);
}
}
Now I have tried to look at the logic, constructor is properly defined in the answer.dart file and it has been handeled well in the main.dart as well.
I am still learning and running out of options to solve this error.
can anyone please help to resolve this error.
Change it to this:
onPressed: ()=> selectHandler()

The element type 'Question' can't be assigned to the list type 'Widget'

I can't use my own Class/Widget Question() from question.dart to main.dart (ERR Location 3rd line after body):
import 'package:flutter/material.dart';
import './question.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
var questionIndex = 0;
// State of function that process data to UI
void _answerQuestion() {
setState(() {
questionIndex = questionIndex + 1;
});
print(questionIndex);
}
void _pangBawas() {
setState(() {
questionIndex = questionIndex - 1;
});
print(questionIndex);
}
// End of State
// This section is responsible for builing UI
#override
Widget build(BuildContext context) {
var questions = [
'What\'s your favorite color?',
'What\'s your favorite animal?',
'What\'s your favorite food?',
'What\'s your favorite color?',
'What\'s your favorite dress?',
'What\'s your favorite position?',
];
// Start of UI
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: Column(
children: [
Question( //ERROR: The element type 'Question' can't be assigned to the list type 'Widget'.
questions[questionIndex],
),
RaisedButton(
child: Text('Answer 1'),
onPressed: _answerQuestion,
),
RaisedButton(
child: Text('Answer 2'),
onPressed: () => _pangBawas,
),
RaisedButton(
child: Text('Answer 3'),
onPressed: () {
//....
print('Hi');
}),
],
),
),
);
// End of UI
}
}
There's no error here, I only get error using Question() on my main.dart file
import 'package:/flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
child: Text(
questionText,
),
);
}
}
Making use of interpolation solves some errors and displays the error to you in your UI. The code below works just fine:
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questiontext;
Question(this.questiontext);
#override
Widget build(BuildContext context) {
return Text("$questiontext");
}
}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
var questionIndex = 0;
// State of function that process data to UI
void _answerQuestion() {
setState(() {
questionIndex = questionIndex + 1;
});
print(questionIndex);
}
void _pangBawas() {
setState(() {
questionIndex = questionIndex - 1;
});
print(questionIndex);
}
// End of State
// This section is responsible for builing UI
#override
Widget build(BuildContext context) {
var questions = [
'What\'s your favorite color?',
'What\'s your favorite animal?',
'What\'s your favorite food?',
'What\'s your favorite color?',
'What\'s your favorite dress?',
'What\'s your favorite position?',
];
// Start of UI
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: Column(
children: [
Question(
//ERROR: The element type 'Question' can't be assigned to the list type 'Widget'.
"${questions[questionIndex]}",
),
RaisedButton(
child: Text('Answer 1'),
onPressed: _answerQuestion,
),
RaisedButton(
child: Text('Answer 2'),
onPressed: () => _pangBawas,
),
RaisedButton(
child: Text('Answer 3'),
onPressed: () {
//....
print('Hi');
}),
],
),
),
);
// End of UI
}
}
You could add itinerary operator to check If the Widget that is returned from the Question class is null or not. This happens because the Column's children widgets can't be null.
body: Column(
children: [
Question(questions[questionIndex]) == null
? SizedBox()
: Question(questions[questionIndex]),
This way if the widget returned from the Question class is null, then the Column will create a SizedBox instead of the Container + Text.

Flutter / Dart / NoSuchMethodError

I have not been able to fix the error for 2 hours. Maybe one of you can help me. You can find a photo below.
What the Debug Console also tells me is:
[ The following NoSuchMethodError was thrown building MyApp (dirty, state: _MyAppState#c7f7e):
I/flutter (17681): The method 'map' was called on null.
I/flutter (17681): Receiver: null
I/flutter (17681): Tried calling: map<Answer>(Closure: (String) => Answer)]
import 'package:flutter/material.dart';
import './question.dart';
import './answer.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
var _questionIndex = 0;
void _answerQuestion() {
setState(() {
_questionIndex = _questionIndex + 1;
});
print(_questionIndex);
}
#override
Widget build(BuildContext context) {
const questions = const [
{
'questionText': 'What\'s your favorite color?',
'answer': ['Black', 'Yellow', 'white', 'green'],
},
{
'questionText': 'What\'s your favorite animal?',
'answer': ['Lion', 'Rabbit', 'Snake', 'Elephant'],
},
{
'questionText': 'What\'s your favorite instructor?',
'answer': ['Flo', 'Viona', 'Flint', 'Flo'],
},
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App!'),
),
body: Column(
children: [
Question(
questions[_questionIndex]['questionText'],
),
...(questions[_questionIndex]['answers'] as List<String>)
.map((answer) {
return Answer(_answerQuestion, answer);
}).toList()
],
),
),
);
}
}
import 'package:flutter/material.dart';
//import './main.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Text(
questionText,
style: TextStyle(fontSize: 28),
textAlign: TextAlign.center,
),
);
}
}
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final Function selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
child: Text(answerText),
onPressed: selectHandler,
),
);
}
}
That shows me the app
There are no key called answers in your map. Instead it is called answer. So questions[_questionIndex]['answers'] will return null since the [] operator for Map is documented as:
Returns the value for the given key or null if key is not in the map.
https://api.dart.dev/stable/2.8.3/dart-core/Map/operator_get.html
Its due to higher Flutter version you are using. Do the change in pubspec.yaml file. Change the version to 2.11.0
environment:
sdk: ">=2.11.0 <3.0.0"