Reputation: 4044
In the flutter Examples page, there is a project entitled "Sending Data to a new screen". I have question reguarding the constructor on line 65.
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
What is the super(key: key)? Could I get explanation of the entire line please. The Code is here....
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
}
void main() {
runApp(MaterialApp(
title: 'Passing Data',
home: TodosScreen(
todos: List.generate(
20,
(i) => Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
),
),
));
}
class TodosScreen extends StatelessWidget {
final List<Todo> todos;
TodosScreen({Key key, @required this.todos}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos'),
),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
// When a user taps on the ListTile, navigate to the DetailScreen.
// Notice that we're not only creating a DetailScreen, we're
// also passing the current todo through to it!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(todo: todos[index]),
),
);
},
);
},
),
);
}
}
class DetailScreen extends StatelessWidget {
// Declare a field that holds the Todo
final Todo todo;
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
@override
Widget build(BuildContext context) {
// Use the Todo to create our UI
return Scaffold(
appBar: AppBar(
title: Text("${todo.title}"),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text('${todo.description}'),
),
);
}
}
Upvotes: 42
Views: 111338
Reputation: 1
Constructor
class MyApp extends StatefulWidget {
//create private named constructor
MyApp._internal();
// using this private named constructor by creating the instance of it
// it must be final so it can't be changed.
static final MyApp instance =
MyApp._internal(); // Singleton or single instance
//factory for the class instance
factory MyApp() => instance; // returns the instance of the class constructor
@override
State<MyApp> createState() => _MyAppState();
}
Upvotes: 0
Reputation: 10462
Here is my detailed understanding on Flutter constructor
There will be only ONE constructor in a class, but could be multiple factory methods.
These are the traditional parameters which are passed in same sequence as defined in constructor.
MyWidget(String param1, int param2) { debugPrint("Positional Optional $param1, $param2"); }
Calling
MyWidget('Param 1 Passed',2,)
Standard practice followed in flutter like where we quote param_name:value
. Below is example
MyWidget(String param1, {int? param2}) { debugPrint("Positional Optional $param1, $param2"); }
Calling
MyWidget('Param 1 Passed',param2: 2,)
The optional parameters are wrapped in square brackets [ ]
MyWidget(String param1, [int? param2]) { debugPrint("Positional Optional, $param1, $param2"); }
Now as the param 2 is in between [ ]
, it makes the param 2 optional. so below are 2 ways to call it.
Way 1 : not passing param 2, the constructor will treat it as null if not passed.
MyWidget('Param 1 Passed',)
Way 2 : passing both params
MyWidget('Param 1 Passed',123)
When the parameter is to be passed mandatorily, we can use this by using keyword required
along with the { }
.
Rule : required
cannot be used with optional params i.e. [ ]
. Obviously, if it's a required param, it cannot be wrapped in optional [ ]
MyWidget(String param1, {required int param2}) { debugPrint("Positional Optional, $param1, $param2"); }
Calling
MyWidget('Param 1 Passed', param2: ,123)
Colons are mainly used for the constructor parameter initialisation.
Rule : Initialisation cannot be done for params, it can only be for variables declared in class strTxt
in this case.
String strTxt; MyWidget(String param1, int param2) : strTxt = "Some Value" { debugPrint("Positional Optional, $param1, $param2, $strTxt"); }
Calling
MyWidget('Param 1 Passed', 123)
Result : Notice the "Some Value" in debugPrint
log which we set in :
Positional Optional, Param 1 Passed, 123, Some Value
You might recall that in Android and some other languages, we pass the value in parameter and then equate it with class level variable. This is entirely shorten in Flutter by simply using this.class_level_var_name
. It simply assigns the passed value to that class level variable.
MyWidget(this.strTxt, int param2) { debugPrint("Positional Optional, $strTxt, $param2"); }
Calling
MyWidget('Param 1 Passed', 123)
Result
Positional Optional, Param 1 Passed, 123
?
OR required
declarationDeclaring nullable is required ONLY when we make the parameter optional [ ]
or Named { }
, for parameter defined as normal, doesn't require the required
or nullable ?
Notice ?
in param2
MyWidget(this.strTxt, {int? param2}) { debugPrint("Positional Optional, $strTxt, $param2, $strTxt"); }
Notice required
MyWidget(this.strTxt, {required int param2}) { debugPrint("Positional Optional, $strTxt, $param2, $strTxt"); }
Upvotes: 11
Reputation: 511626
This is an example to supplement Günter Zöchbauer's explanation. It is the constructor of the Align widget.
class Align extends SingleChildRenderObjectWidget {
// constructor
const Align({
Key key, // named parameter
this.alignment = Alignment.center, // named parameter
this.widthFactor, // named parameter
this.heightFactor, // named parameter
Widget child // named parameter
}) : assert(alignment != null), // initializer list
assert(widthFactor == null || widthFactor >= 0.0), // initializer list
assert(heightFactor == null || heightFactor >= 0.0), // initializer list
super(key: key, child: child); // initializer list
// class variables
final AlignmentGeometry alignment;
final double widthFactor;
final double heightFactor;
More notes:
this.
prefix are variables of the superclass.this.
are variables defined in the current class.Upvotes: 35
Reputation: 657118
The constructor has two named parameters.
Named parameters are optional by default.
@required
is an annotation recognized by the Dart analyzer and produces a warning if not passed when invoked at build time (it has no effect at run time).
:
starts the "initializer list", a comma sparated list of expressions executed before the constructors of the super classes and therefore also before the contructors body.
It is often used to check parameter values using assertions and to initialize final fields with calculated values.
A limitation is, that expressions can't read-access this.
(implicitely or explicitely) because the object initialization is not completed before the super constructors are executed.
The last element in the initializer is an implicit call to the default constructor of the super class if omitted, or the call to a specific constructor of the current class or the super class if given.
In the example in your question the key
parameter passed to the constructor is forwarded to the named parameter key
of the unnamed constructor of the super class.
Upvotes: 39