so I am currently learning Dart (Flutter) and I have come to something I can't really understand. So I'm hoping that someone will be able to point out the obvious thing here :)
If I write my code like this:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: QuizPage(
title: 'Quiz APP',
questions: [
{'question': 'Color?', 'answers': ["Red", "Blue", "Green", "Black"]},
{'question': 'Animal?', 'answers': ["Cat", "Dog", "Snake", "Rabbit"]},
]),
);
}
}
class QuizPage extends StatefulWidget {
QuizPage({super.key, required this.title, required this.questions});
final String title;
final List<Map<String, Object>> questions;
@override
State<StatefulWidget> createState() {
return _QuizPageSate();
}
}
It works, but I have later to cast the answers Object with as List<String>
. However, if I directly define the questions
type as:
final List<Map<String, List<String>>> questions;
it will not work and throw an error:
The element type 'String' can't be assigned to the map value type 'List<String>'.
It seems like it doesn't know how to interpret the type I pass in. Do all non "primitive" types inside a Map
have to be defined as Object
or am I missing something fundamental here?
CodePudding user response:
In your example you declare the following JSON:
[
{
'question': 'Color?',
'answers': [
"Red", "Blue", "Green", "Black"
]
},
{
'question': 'Animal?',
'answers': [
"Cat", "Dog", "Snake", "Rabbit"
]
},
]
This, in Dart, is a List
of Map
s, and those maps have a key of String
and a value of either String
(the question) or a List
of String
(the answers).
The problem is this "either", you cannot have a type of either String
or List<String>
, so you have to use Object
or dynamic
, which both accept any type.
So, when you used Object
, it worked because it accepts anything, but you have to cast it correctly later. And when you used List<String>
, the question ('Color?', 'Animal?'), which is not a List<String>
, stopped being a valid type.
What you can do to avoid dynamic types is to use classes. Make your QuizPage
accept a List<QuizQuestion>
, for example.
class QuizQuestion {
final String question;
final List<String> answers;
QuizQuestion(this.question, this.answers);
}
And then do:
QuizPage(
title: 'Quiz APP',
questions: [
QuizQuestion('Color?', ["Red", "Blue", "Green", "Black"]),
QuizQuestion{'Animal?', ["Cat", "Dog", "Snake", "Rabbit"]),
],
),
CodePudding user response:
In your questions
list first map contain two key
: value
. One of the values are String
and the other is list
, if you define the value as dynamic
or Object
its ok, but if you set it as list
because of first value it through error.
Object
or dynamic
means you don't know the type and every type is accepted.
So the only option you have is cast your answers
to List<String>
which you are doing it now.