Why is key required in constructor? - flutter

I have created class which extend StatefulWidget
class RegistrationPage extends StatefulWidget {
final String email;
const RegistrationPage({Key key, required this.email}) : super(key: key);
#override
_RegistrationPage createState() => _RegistrationPage();
}
The problem is android studio force me to put required before Key key. I googled some of examples how to pass values from screen to another screen and I have never seen that someone used required with Key.
I do it within:
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => RegistrationPage(email: email),
),
);
so just to pass email value. I need to make Key nullable to make it work.
Am I doing something wrong?

Because you're using null-safe Dart and key can't be null because it has a non-nullable type Key.
Solutions:
Use required
FooPage({required Key key});
Make key nullable.
FooPage({Key? key});
Remove key altogether.
FooPage();

I think your project is in null safety, with null safety a variable or object cannot be null execept if it is declared nullable.
Try adding a ? after Key:
class RegistrationPage extends StatefulWidget {
final String email;
const RegistrationPage({Key? key, required this.email}) : super(key: key);
#override
_RegistrationPage createState() => _RegistrationPage();
}
or you can simply delete the Key override:
class RegistrationPage extends StatefulWidget {
final String email;
const RegistrationPage({required this.email});
#override
_RegistrationPage createState() => _RegistrationPage();
}
I suggest you to read https://dart.dev/null-safety/understanding-null-safety

You're not doing anything wrong by making Key key nullable. The super constructors that you're passing the key to accept the nullable type.
So
const RegistrationPage({Key? key, required this.email}) : super(key: key);
is the norm as there is no reason to constrain the type by making it non-nullable and required.
If you have no need for keys with this widget, you can omit the super constructor and the key parameter completely.

Related

error: 1 positional argument(s) expected, but 0 found

When I want to declare this function in my main.dart
class MapEqualColorMappingPage extends SampleView {
const MapEqualColorMappingPage(Key key) : super(key: key);
#override
_MapEqualColorMappingPageState createState() =>
_MapEqualColorMappingPageState();
}
class _MapEqualColorMappingPageState extends SampleViewState {
List<_CountryTimeInGMT> _timeZones;
MapShapeSource _mapSource;
...
}
i get the following error
error: 1 positional argument(s) expected, but 0 found.
'/map': (context) => MapEqualColorMappingPage(), //The error is HERE
what should id ?
Instead of MapEqualColorMappingPage(Key key) write MapEqualColorMappingPage({Key? key})
class MapEqualColorMappingPage extends SampleView {
const MapEqualColorMappingPage({Key? key}) : super(key: key);
#override
_MapEqualColorMappingPageState createState() =>
_MapEqualColorMappingPageState();
}
class _MapEqualColorMappingPageState extends SampleViewState {
List<_CountryTimeInGMT> _timeZones;
MapShapeSource _mapSource;
...
}
Here
const MapEqualColorMappingPage(Key key) : super(key: key);
you are stating that the constructor must have an argument of type Key, and here
'/map': (context) => MapEqualColorMappingPage()
you're trying to use the same constructor without any kind of argument.
You can:
add a Key argument when you use the constructor
remove the Key argument from the constructor declaration
put the Key argument in the declaration in curly braces in order to make it optional
You are not passing Key parameter.
const MapEqualColorMappingPage(Key? key) : super(key: key);
Mark it as optional Key?

Widget is null inside initState

It's the first time a use Flutter (2.8.1) and I'having problems trying to undestrand what's going wrong.
I have a Stateful widget like this:
class SimpleWidget extends StatefulWidget {
final Type2 aValue;
const SimpleWidget({Key key, #required this.aValue}) : super(key: key);
#override
_SimpleWidgetState createState() => _SimpleWidgetState();
}
class _SimpleWidgetState extends State<SimpleWidget> {
Type1 color;
#override
void initState() {
super.initState();
color = widget.aValue; // <-- widget is null
}
...
}
that I call in this way:
List<Type1> something = await showDialog(
context: context,
builder: (context) {
print('currentElement.aValue: ${currentElement.aValue}'); // not null
return SimpleWidget(aValue: currentElement.aValue);
},
);
Why is widget.aValue == null in initState()? How can I solve it?
There are some error in your coding;
The first one is construction of SimpleWidget
const SimpleWidget({Key key, #required this.aValue}) : super(key: key);
when you call like SimpleWidget(aValue: currentElement.aValue); It will should error like key can not be null. You can use ? to make it nullable. Also, # should be remove, it is a syntax error
The correct one looks like
const SimpleWidget({Key? key, required this.aValue}) : super(key: key);
The second one is in SimpleWidgetState
You can change Type1 color; to late Type1 color;
Or make it nullable.
For more details, you can check flutter codelabs

How to Add and Use key in Custom widget constructors

I got notification warning (Not Error) about Use key in widget constructors. let say I have stateless class like this :
class TeaTile extends StatelessWidget {
final TheTea? tea;
const TeaTile({this.tea}); //the warning in hire!
#override
Widget build(BuildContext context) {
return Container();
}
}
the basic stateless format has a key like this :
class TeaTile extends StatelessWidget {
const TeaTile({ Key? key }) : super(key: key); //this one
#override
Widget build(BuildContext context) {
return Container();
}
}
I know how to disable the key rule use_key_in_widget_constructors: false. but I don't want to do it. so, how I add key in
final TheTea? tea;
const TeaTile({this.tea});
to solve the warning notification?
Update for Dart 2.17 using Super Initializers:
final TheTea? tea;
const TeaTile({ super.key, this.tea });
The super keyword in a constructor is a shortcut for the method below.
Older Dart versions:
final TheTea? tea;
const TeaTile({ Key? key, this.tea }) : super(key: key);
Basically a combination of both, you're still taking a named parameter key, that will pass it's value to the super constructor, and another named parameter tea that would set your final variable value.

Flutter calling StatefulWidget's constructor caused expression can't be evaluated

I'm creating a stateful widget, and trying to call the superclass construction using super(key: key. However, I'm getting an error saying:
class ArticlesPage extends StatefulWidget {
ArticlesPage({Key key}) {
super(key: key);
}
#override
_ArticlesPageState createState() => _ArticlesPageState();
}
For dart, super should be called in the initializer list. Ex:
ArticlesPage({Key key}) : super(key: key);
If you also want to initialize fields here, you should do this before the super call. super should always be last in the initializer list.
If you want to save key from --> Key key as a class variable also.
In this case, you will get a default GlobalKey value if it's not passed during constructor initialize.
AppStateFullWidget({Key key}):super(key: key ?? GlobalKey()){
_key = super.key;
}

Make Function parameter optional in custom widget flutter

I try to create some custom widgets with some parameters in the constructor. This widget has some optional and required parameters.
how can make Function type parameter optional in my Widget.
class TextInputWithIcon extends StatefulWidget {
final String iconPath;
final String placeHolder;
final Function(bool) onFocusChange;
const TextInputWithIcon(
{Key key,
#required this.iconPath,
this.placeHolder = "",
this.onFocusChange})
: super(key: key);
#override
_TextInputWithIconState createState() => _TextInputWithIconState();
}
class _TextInputWithIconState extends State<TextInputWithIcon> {
#override
Widget build(BuildContext context) {
return MY_WIDGET;
}
}
Optional parameters can be either positional or named, but not both.
Named parameters are optional by default so you don't have to assign the default value.
If a parameter is optional but can’t be null, provide a default value.
With null safety
class TextInputWithIcon extends StatefulWidget {
final String iconPath;
final String placeHolder;
final Function(bool)? onFocusChange; // nullable and optional
const TextInputWithIcon(
{Key? key,
required this.iconPath, // non-nullable and required
this.placeHolder = "", // non-nullable but optional with a default value
this.onFocusChange, // nullable and optional
})
: super(key: key);
#override
_TextInputWithIconState createState() => _TextInputWithIconState();
}
Without null safety
const TextInputWithIcon(
{Key key,
#required this.iconPath,
this.placeHolder = "",
this.onFocusChange
})
: super(key: key);
Usage:
void _focusChanged(bool value) {
// using null-aware operator (for both with and without null safety)
onFocusChange?.call(value);
// or without null-aware operator
// with null safety
if(onFocusChange != null) {
onFocusChange!(value);
}
// without null safety
if(onFocusChange != null) {
onFocusChange(value);
}
}
Dart 2.17 update:
Although it often makes sense to place positional arguments first, named arguments can be placed anywhere in the argument list when it suits your API:
repeat(times: 2, () {
...
});
Have a look at Optional Parameters to understand better.
Edit: Thank you Jonah Williams to clarification.
You can use a default value that does nothing:
class TextInputWithIcon extends StatefulWidget {
final String iconPath;
final String placeHolder;
final Function(bool) onFocusChange;
const TextInputWithIcon(
{Key key,
#required this.iconPath,
this.placeHolder = "",
this.onFocusChange = _dummyOnFocusChange})
: assert(onFocusChange != null), super(key: key);
#override
_TextInputWithIconState createState() => _TextInputWithIconState();
static dynamic _dummyOnFocusChange(bool val) {}
}
I created a static named function instead of just a closure as a default value because closures are not const and currently default values need to be const.
I added the assert(...) to ensure that an error is shown when null is passed explicitly.
Another option if you don't like named parameters (like me :/) is:
function_name (argument1, [argument2]) {
// statements
}
arguments in brackets are optional.
source