I have been trying to get an clear explanation for what : means in dart.
As far as I can tell it seems so be some kind of operator , but I can't get a clear cut explanation of what exactly it does.
I understand that it gets used to so assign stuff to other stuff , but I am unsure of the specifics.
I have tried googling it , no luck.
I have tried searching through the dart documentation.
https://dart.dev/guides/language/language-tour#operators
I know that it gets used as part of conditional expressions like here:
https://dart.dev/guides/language/language-tour#conditional-expressions
Here are examples of how it gets used:
Example 1 :
class someBloc extends Bloc<someEvent, someState> {
someBloc() : super(someState.initial());
}
Example 2 :
class someClass {
final String requestType;
final String name;
factory someClass.fromJson(Map<String, dynamic> json) {
return SomeClass(
requestType: json['Type'],
name: json['Name']);
}
}
In examples 1 & 2:
The : is used to set a named parameter. For example, let's say I want to create a Card widget. The card widget optionally takes a named parameter called elevation. Therefore, I can do this:
Card(
elevation: 4.0,
)
Another way : is used is for writing quick conditional expressions.
final String isMyListEmpty = myList.isEmpty ?? 'Yes, the list is empty' : 'No, the list is not empty';
In this example, our condition is myList.isEmpty. If this condition is true, the first expression after ?? is returned. Else, if the condition is false, the expression after the : is returned.
It's just an assignment operator. You assign a value to a widget property. For example, Container widget has many properties, like color or height:
Container(
margin: const EdgeInsets.all(10.0),
color: Colors.amber[600],
width: 48.0,
height: 48.0,
),
Related
I have simple code as follows:
class TestPage extends StatelessWidget {
static String myString = 'abc';
static double myDouble;
#override
Widget build(BuildContext context) {
try {
myDouble = double.parse(myString) + 5;
} catch (e) {
print(e);
}
return Scaffold(
body: Center(
child: Text(
'$myDouble' ?? 'Ok',
style: TextStyle(fontSize: 50),
),
),
);
}
}
Since myDouble is going to return null, I expect the Text widget to take in 'Ok' and rendre the same. However, I still see null shown on the screen.
Any help as to why this is not working please. Thank you.
Additionally, I do not understand why I cannot use try catch block before build method as it gives error.
Disclaimer: This question is regarding Dart before the null-safety. With null-safety on, this scenario would not happen.
In your case, even though myDouble is null, when you do
'$variable'
You are creating a new string which isn`t null (which is denoted by the " or ' signs).
So the 'ok' after the null-aware operator would never be called anyway.
Also, using ${var} inside a string is called String Interpolation, which as the documentation states:
To get the string corresponding to an object, Dart calls the object’s toString() method.
And, the toString() method on a null object returns simply null, which results in your text displaying null.
There are many ways for the desired result, you could do, as an example:
(myDouble == null) ? 'ok' : '$myDouble' ,
Just as a reminder, Dart now supports null safety, which you should be using in new codes (and migrating old ones). With null safety, you probably would have notice this error before.
Text('$myDouble') converts the null to string null
'$myDouble' is now 'null'(string)
to manage null String variables you can do this either of the ways
Text(myDouble == null ? 'Ok' : myDouble.toString);
Guys,why it is an obligation to put the 'required' keyword when creating named constructors?
How can i create named constructors without being required thought?
class IconPage extends StatelessWidget {
IconPage({required this.icon,required this.label});
final String label;
final IconData icon;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: Colors.white,
size: 70,
),
SizedBox(height: 10),
Text(
label,
style: kStandartFontSize,
),
],
);
}
}
Here's the error message that apears when i try to create named constructors without the required keyword:
The parameter 'label' can't have a value of 'null' because of its type, but the implicit
default value is 'null'.
Try adding either an explicit non-'null' default value or the 'required' modifier.
The required keywords means that the paramater is mandatory. If you don't want to use required you have to change your variable to be nullable with the ?. But then you have to make sure that you handle your parameters which can be null.
class IconPage extends StatelessWidget {
IconPage({this.icon, this.label});
final String? label;
final IconData? icon;
...
}
As a compliment to the other answer:
You created your constructor using named parameters. They are called named parameters because when you call your function, you call it like this:
function (namedParameter1: "abc", namedParameter2: "123");
So you can change the order of parameters or not call one parameter at all.
One way to "not use the required keyword" would be to not use named parameters, but the regular "positional parameters":
IconPage(this.icon, this.label);
In this case, the order of the parameters you pass would matter, and all of them would be required by default.
So it should be called like this:
IconPage(IconData(...), "abc"),
Although this is not so common when writing custom Widgets (and I don't recommend it also), with simpler functions this can be used without compromising the readability. You can read more about the difference between positional and named parameters here.
Am trying to simply print some data from an array but I keep getting an error that say list function can't be assigned to type widget but I've checked everything and each component looks like it should be okay, so let's start with data:
class GameOptions {
String name;
int key;
int hidden;
int random;
GameOptions({this.name, this.key, this.hidden, this.random});
}
// Populate the Data
List <GameOptions> options = [
GameOptions(name : "Town Hall", key : 001, hidden:1, random: 0),
GameOptions(name : "Chapel", key : 003, hidden:1, random: 0),
GameOptions(name : "Tavern", key : 002, hidden:1, random: 0),
GameOptions(name : "Merchant", key : 004, hidden:1, random: 0),
] ;
And then the code where I'm calling this data up for a text print:
Expanded(
flex:3,
child: Column (
children: options.map((name) => Text(name)).toList,
),
),
It's the children line where I get the error. Thanks in advance, I can't fathom if it's simple mis-understanding of syntax or if there is a problem in building my List.
Actually you are passing the whole GameOptions object to the text widget rather than passing its name property over there:
children: options.map((name) => Text(name)).toList,
Instead it should be like this
children: options.map((gameOption) => Text(gameOption.name)).toList,
Just replace this single line and your code will work perfectly.
I'm new to Flutter and am working through the intro course on Udacity. In one of the tasks, I was trying to follow the code and I can't make much sense of it. Here's the code from the solution of the project (I've cut and paste the parts that matter, and also legal disclaimer I do not own any of this code, it's from the sample Flutter Udacity project):
Widget build(BuildContext context) {
final input = Padding(
padding: _padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(...),
_createDropdown(_fromValue.name, _updateFromConversion),
],
),
);
}
void _updateFromConversion(dynamic unitName) {
setState(() {
_fromValue = _getUnit(unitName);
});
if (_inputValue != null) {
_updateConversion();
}
}
Widget _createDropdown(String currentValue, ValueChanged<dynamic> onChanged) {
return Container(
margin: EdgeInsets.only(top: 16.0),
decoration: BoxDecoration(...),
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Theme(...),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: currentValue,
items: _unitMenuItems,
onChanged: onChanged,
style: Theme.of(context).textTheme.title,
),
),
),
),
);
}
Here's where I'm stuck. _updateFromConversion requires an input parameter unitName. But when they call it, in _createDropdown, they don't pass any. So how does _updateFromConversion know what unitName is? Also, is _updateFromConversion executed before _createDropdown, or is it executed when the "onChanged" property of DropdownButton is set?
Second question: they're passing that function with return type void into _createDropdown, which is expecting ValueChanged. Shouldn't this throw an error?
If someone can explain the flow of this code and what I am missing I would greatly appreciate it.
Thank you!
You seem to be misunderstanding the assignment of a variable to a function for a function call.
Let me try to show it with example code.
void _updateFromConversion(dynamic unitName) {
print("Unit name: $unitName");
}
class SomeClass {
void Function(dynamic arg) myFunction;
}
void main() {
final c = SomeClass()..myFunction = _updateFromConversion;
print("Created c. Calling its function");
c.myFunction("foo");
print("Done");
}
When you run this code, you will see this printed:
Created c. Calling its function
Unit name: foo
Done
This shows that the _updateFromConversion function is not called when you create the SomeClass instance in SomeClass()..myFunction = _updateFromConversion;. This is only an assignment (it assigns to the field myFunction the value _updateFromConversion... yes, in Dart a function itself can be a value)!
You should know that because there's no () after the function name, and function invocation in Dart always must contain the list of arguments between () even if it's empty.
So, here's where the function is invoked:
c.myFunction("foo");
See? There's a list of arguments containing a single value, "foo". That's why the function then prints Unit name: foo, because the argument unitName takes the value "foo".
TL;DR
This is a function invocation:
c.myFunction("foo");
This is NOT:
c.myFunction;
Yashvin,
In dart function can be passed as parameter to other functions. This is usually used to pass callbacks for instance.
In example you provided, function _updateFromConversion is passed as parameter onChanged to another function _createDropdown.
In that function it will be assigned to onChanged listener of DropdownButton button.
Every time value of DropdownButton changes, this function will be invoked and will be passed selected value of DropdownButton.
I created a method below to loop through my list because I don't want to write again and again of these few lines but the parameter I pass to the Text widget and also value argument are error and it said Invalid constant value. How can I achieve this? I'm new to flutter. Please help me.
PopupMenuItem _createMenuItems(final String a) {
return const PopupMenuItem(
value: a,
child: Text(a),
);
}
Have your tried simply returning PopupMenuItem without const modifier like below?
PopupMenuItem _createMenuItems(final String a) {
return PopupMenuItem(
value: a,
child: Text(a),
);
}