Reputation: 3229
In the flutter docs there's sample code for a stateless widget subclass as shown:
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
@override
Widget build(BuildContext context) {
return new Container(color: const Color(0xFF2DBD3A));
}
}
and this
class Frog extends StatelessWidget {
const Frog({
Key key,
this.color: const Color(0xFF2DBD3A),
this.child,
}) : super(key: key);
final Color color;
final Widget child;
@override
Widget build(BuildContext context) {
return new Container(color: color, child: child);
}
}
What is a key and when should this super constructor be used? It seems like if you have your own constructor you must have {Key key} why? I've seen other examples where the super keyword is not used so this is where my confusion is.
Upvotes: 137
Views: 41420
Reputation: 511866
Keys are IDs for widgets. All widgets have them, not just StatelessWidgets. They are used by the Element tree to determine if a widget can be reused or if it needs to be rebuilt. When no key is specified (the usual case), then the widget type is used to determine this.
Keys are useful for maintaining state when the number or position of widgets changes. If there is no key then the Flutter framework can get confused about which widget changed.
Only use them when the framework needs your help to know which widget to update.
Most of the time you don't need to use keys. Since keys are mostly only useful for maintaining state, if you have a stateless widget whose children are all stateless, then there is no need to use a key on it. It won't hurt to use a key in this case, but it also won't help.
There are some micro-optimizations you can make using keys. See this article.
Put the key at the part of the widget tree where the reordering or addition/deletion is taking place. For example, if you are reordering the items of a ListView whose children are ListTile widgets, then add the keys to the ListTile widgets.
A key is just an id, but the kind of ID you use can vary.
A ValueKey is a local key that takes a simple value like a string or integer.
If you widget is displaying more complex data than a single value, then you can use an ObjectKey for that widget.
This type of key is guaranteed to give you a unique ID every time. If you use it, though, do NOT put it in the build
method. Otherwise your widget will never have the same ID and so the Element tree will never find a match to reuse.
GlobalKeys can be used to maintain state across your app, but use them sparingly because they are similar to global variables. It is often preferable to use a state management solution instead.
Upvotes: 55
Reputation: 71
With Dart 2.12 or later, add ?
after Key to make it optional if you want.
class Frog extends StatelessWidget {
const Frog({
Key? key,
this.color: const Color(0xFF2DBD3A),
this.child,
}) : super(key: key);
final Color color;
final Widget child;
@override
Widget build(BuildContext context) {
return new Container(color: color, child: child);
}
}
Upvotes: 1
Reputation: 19415
Key is object that is used to identify a widget uniquely.
They are used to access or restore state In a StatefulWidget
(Mostly we don't need them at all if our widget tree is all Stateless Widgets).
There are various types of key that I will try to explain on the basis of usage.
Purpose (key types
)
i.e. remove / add / reorder item to list
in stateful widget like draggable todo list where checked items get removed➡️ ObjectKey, ValueKey & UniqueKey
➡️ GlobalKey
➡️ GlobalKey
➡️ GlobalKey
➡️ UniqueKey
➡️ ValueKey
➡️ ObjectKey
➡️ GlobalObjectKey, LabeledGlobalKey whichever is appropriate, similar logic to ValueKey and ObjectKey
string/number
as key, it defeats the purpose of keys ❌Upvotes: 12
Reputation: 181
The Key is an optional parameter needed to preserve state in your widget tree, you have to use them if you want to move a collection of elements in your tree and preserve the state of them.
The best explanation can be found in this video by Google When to Use Keys - Flutter Widgets 101 Ep. 4
Upvotes: 4
Reputation: 277077
TLDR: All widgets should have a Key key
as optional parameter or their constructor.
Key
is something used by flutter engine at the step of recognizing which widget in a list as changed.
It is useful when you have a list (Column
, Row
, whatever) of widgets of the same type that can potentially get removed/inserted.
Let's say you have this (code not working, but you get the idea) :
AnimatedList(
children: [
Card(child: Text("foo")),
Card(child: Text("bar")),
Card(child: Text("42")),
]
)
Potentially, you can remove any of these widgets individually with a swipe.
The thing is, our list has an animation when a child is removed. So let's remove "bar".
AnimatedList(
children: [
Card(child: Text("foo")),
Card(child: Text("42")),
]
)
The problem: Without Key
, flutter won't be able to know if the second element of your Row
disappeared. Or if it's the last one that disappeared and the second has its child change.
So without Key
, you could potentially have a bug where your leave animation will be played on the last element instead!
This is where Key
takes place.
If we start our example again, using key we'd have this :
AnimatedList(
children: [
Card(key: ObjectKey("foo"), child: Text("foo")),
Card(key: ObjectKey("bar"), child: Text("bar")),
Card(key: ObjectKey("42"), child: Text("42")),
]
)
notice how the key is not the child index but something unique to the element.
From this point, if we remove "bar" again, we'll have
AnimatedList(
children: [
Card(key: ObjectKey("foo"), child: Text("foo")),
Card(key: ObjectKey("42"), child: Text("42")),
]
)
Thanks to key
being present, flutter engine now knows for sure which widget got removed. And now our leave animation will correctly play on "bar" instead of "42".
Upvotes: 181