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.
Related
I am new to flutter and confused with it's constructor.
For example:
sample 1:
class MyContainer extends StatelessWidget {
final Color color;
const MyContainer({Key key, this.color}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
sample 2:
class MyContainer extends StatelessWidget {
final Color color;
MyContainer({this.color});
#override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
I removed const and key in sample 2, and both of sample1 and sample2 work well.
Is there any potential risk in sample 2?
You would use a const constructor when you dont want this widget to be rebuild.
A constant widget is like the constant pi, it won't change.
If you have state however you want to use the normal constructor in Sample 2, because the widget changes and cant be constant then.
So you get a slight performance increase when you use const in places where it makes sense (because it wont be rebuild).
The key property is another topic.
const
A variable with the const keyword is initialized at compile-time
and is already assigned when at runtime.
You can’t define const inside a class. But you can in a
function.
For Flutter specific, everything in the build method won’t be
initialized again when the state is updated.
const can’t be changed during runtime.
When to use const?
-
Use const: If you are sure that a value isn’t going to be changed when running your code. For example, when you declare a sentence that always remains the same.
when you use const with constructor, it is compile time constant and all values given in constructor must be constant,
try giving unconstant values to const Constuctor to see the difference
I want to be able to pass a future as an argument in a class constructor to be used later. Here's the code of the class to help explain...
class Custom extends StatelessWidget {
final String title;
final Future action; //trying to pass a future to be called later
Custom({#required this.title, #required this.action});
#override
Widget build(BuildContext context) {
...
return Column(
children: <Widget> [
Text(title),
RaisedButton(
...
onPressed: () {
action;
}
),
],
),
}
So when I try to build
Custom(title: "print something", action: doSomething())
..what ends up happening is doSomething runs immediately instead of when I press the RaisedButton. If I remove the () at the end of doSomething, I get the error:
The argument type 'Future<dynamic> Function()' can't be assigned to the parameter type 'Future<dynamic>'.
Do I need to do something different in the class constructor? Or if this is not possible, is there a way to achieve this differently?
EDIT:
Based on early answers, I changed my constructor to
final Future Function() action;
Now it builds, but it's still not calling it. I tried creating the future I'm trying to call in both the Custom class and in the class I'm building Custom from, but neither work. Ideally, I'd like to have the Future I'm calling in the class I'm building from. Any suggestions?
EDIT:
This is working now. It wasn't working because besides my changes above, I also had to change onPressed: action()
Try changing the declaration to
final Future Function() action;
And use it without the ()
Custom(title: "print something", action: doSomething)
The error you're seeing is pretty spot on in description. The Future<?> Function() and Future<?> are unrelated types. All the functions you write that you wrap with Future<?> functionName() async are returning an instance of Future but by themselves have nothing to do with Futures, so reference to that function can't be used as a parameter that expects Future type.
Additionally, you need to figure out what to do with generic parameter for the Future data type. If you leave it as Future (which is the same as Future<dynamic> you'll never get compiler errors when forwarding any Future<?> type there but while you won't get any compile errors you can get into runtime issues if the expected output type of that Future turns to be something other than the type you're expecting.
If you're only calling Future<void> method you can simply put Future<void> Function() action; as your field type. If you're going to be calling different data types but only ever calling the same data type on the same instance of Custom widget you can make it generic as well, like this:
class Custom<T> extends StatelessWidget {
final String title;
final Future<T> Function() action;
Custom({#required this.title, #required this.action});
//...
}
Can someone tell me what is happening in this program?
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new StuffInTiles(listOfTiles[index]);
},
itemCount: listOfTiles.length,
),
),
);
}
}
class StuffInTiles extends StatefulWidget{
final MyTile myTile;
const StuffInTiles(this.myTile);
#override
StuffInTilesState createState() => StuffInTilesState();
}
class StuffInTilesState extends State<StuffInTiles> {
#override
Widget build(BuildContext context) {
return Container(child:
//Text(widget.myTile.title),);
_buildTiles(widget.myTile));
}
Widget _buildTiles(MyTile t) {
I want to understand how passing parameters works,why i have
const StuffInTiles(this.myTile);
in this program, what this code is doing?
in my class StuffInTilesState extends State<StuffInTiles> i don't have any constructor, so how this code is working? why my parameters just happen to be there? before i was learning C++, so this is like a magic to me
If you learned C++ you are probably familiar with initializer list, which Dart has as well. In C++ you could do something:
MyClass {
MyClass(MyTitle title) : this.myTitle = title;
final MyTitle myTitle;
}
Which is also valid in Dart. However, Dart allows you to shorthand the call, by automatically assigning the reference to the new class property, without using any intermediate variable.
MyClass(this.myTitle);
Which is basically the same but ensures that any given property won't be null unless you explicitly pass null.
There are other type of constructors available on Dart, such as private constructors, factory constructors and named constructors. You may want to check the official documentation to learn more about it.
By default, when you create classes in Dart, there is just a default constructor implemented.
For example, if you have a class named AwesomeWidget. It will have a default constructor AwesomeWidget() that lets you create an instance of this widget.
So you could use a default constructor in code like so:
//Example 1
return AwesomeWidget();
//Example 2
AwesomeWidget myWidget = AwesomeWidget();
//Example 3
//...
Row(
children: [
Text("Example Code!"),
AwesomeWidget(),
Text("Example Footer Code!"),
],
),
//...
Now if you want to pass some values or some data to your Widget classes then you use the code you have posted above in your question.
The question is: Why would we want to send data to our widgets?
Answer: The biggest use case is when we make our list items as separate widgets. For example, in my food app, I have to show my user's order history in a ListView, so for the UI of each individual list item, I will just make a reusable Widget called OrderHistoryListItem.
In that OrderHistoryListItem, you want to show the date and time of the object. And the order id, and how much the user paid in that order or any other details, so to display this, we send this data to our Reusable Widget List Item, which displays it. Simple as that.
And that is one of the reasons why we pass values to Widgets. As a programmer, you can make use of this handy feature for more complex scenarios, be creative!
When I refactored my Widget in Flutter the following code is generated. However, I still do not understand what is it for and why is it there. I deleted it and nothing broke. Everything is okay. What is it for?
const ReusableCard({
Key key,
}) : super(key: key);
This is the complete class that was refactored:
class ReusableCard extends StatelessWidget {
const ReusableCard({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFF1D1E33),
borderRadius: BorderRadius.circular(10.0),
),
);
}
}
As stated in Dart Language tour:
Subclasses don’t inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, no name) constructor. [...]
By default, a constructor in a subclass calls the superclass’s unnamed, no-argument constructor.
So, in your example, deleting this constructor would call the default constructor of the Stateless Widget class. We can see from the documentation of this class that a optional parameter named key may be passed to it. The ReusableCard constructor you are asking is allowing you to create a Stateless Widget using this key parameter. If you delete this constructor, you won't be able to give this Widget a Key.
A Key is an identifier for Widgets and other elements in the Flutter framework. It is needed in some situations where you must identify the widget. The most common example for this is when you try to swap (or delete) Widgets in a list. To recognize they changed Flutter framework needs the key to identify them. If you are not doing any of these cases, or if you're not using keys at all, it's ok to delete this constructor.
A great official video from Google about keys in Flutter can be seen here.
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,
),