Flutter Community

Articles and Stories from the Flutter Community

Flutter Tutorial

Keys in Flutter

Saurabh Pant
Flutter Community
Published in
5 min readOct 6, 2024

--

In Flutter, we’ve Keys associated with every widget we use and they’re optional. In this article, we’ll explore what do they do or why they exists? In which scenarios it makes more sense to use them.

What does Keys do?

Keys are used to identify a specific widget based on a specific value in a Widget tree. By identifying a widget, we can perform specific operations on it. For instance, this can help in managing the state of a widget while the Widget may be reordered in the Widget tree.

Another example would be that the Widget is placed on multiple screens while maintaining the same state. Element tree takes its Key reference from the Widget tree to maintain the state of the Widget before rendering it on the screen.

This way the use cases becomes limited for Keys. In general cases, we might even don’t require Keys.

So far so cool!

An Use case for Keys

Consider a scenario where we’ve a screen with a Screen Counter Text shown at the top and we’ve two widgets of same type MyWidget.

On clicking on either of the widget A or B, it adds up and increments the Screen Counter Text on the screen and also increments their own counter which is part of each widget itself as shown below.

Next, every time we tap on either of the widget A or B, if the screen counter is even then we show Widget A on top otherwise Widget B. This way we’re reordering them every time.

In this case, we’re dealing with multiple states.

  • State of Screen Counter Text
  • State of individual tap counters on the Widget A and B
  • Widgets reordering

Quick view of demo code

Consider the following code for our MyWidget.

class MyWidget extends StatefulWidget {
const MyWidget({
super.key,
required this.onChange,
required this.title,
});

final Function(int) onChange;
final String title;

@override
State<StatefulWidget> createState() => _MyWidget();
}

// Simple straight
class _MyWidget extends State<MyWidget> {
int counter = 0;

@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
'$counter',
style: const TextStyle(
fontSize: 20,
color: Colors.black45,
),
),
ElevatedButton(
onPressed: () {
setState(() {
counter++;
});
widget.onChange(counter);
},
child: Text(
widget.title,
style: const TextStyle(
fontSize: 20,
color: Colors.black,
),
),
),
],
);
}
}

Now our main screen looks like as follows

class _MyWidget extends State<SampleWidget> {
int screenCounter = 0; // Screen Text Counter

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$screenCounter',
style: const TextStyle(
fontSize: 40,
color: Colors.red,
),
),
const SizedBox(
height: 20,
),
_createWidget( // Widget A
counter.isEven,
),
_createWidget( // Widget B
counter.isOdd,
),
],
);
}

Widget _createWidget(bool status) {
return MyWidget(
title: status ? 'Widget A' : 'Widget B',
onChange: (value) {
setState(() {
screenCounter++;
});
},
);
}
}

How Keys help!

If we run our app, this is how our output would look like

Incorrect output

We can see that the reordering is correctly working, screen text counter is also correctly updating but the individual counter texts are not updating correctly. Why this is happening?

To understand this follow the below image

Here when the element tree is trying to map the elements A and B of widget A and B from Widget tree, at the initial stage, it finds them and place them correctly.

But when we reordered the widgets on the widget tree, element tree tries to check if the same element type is there or not and it finds the same type. So it doesn’t reorder the elements but updates them with the latest state from corresponding widgets from Widget tree as shown below.

So when this happens, the counter states of each Widget A and B remain at the same position and it seems incorrect. So how can this be fixed?

Well! Here comes Keys into the picture. We simply update our Widgets A and B while creating them, by assigning them a Key as shown.

Widget _createWidget(bool status) {
return MyWidget(
// ----- Addition ----
key: ValueKey(status ? 'A' : 'B'), // Adding KEY
// -------------------
title: status ? 'Widget A' : 'Widget B',
onChange: (value) {
setState(() {
counter++;
});
},
);
}

Now if we run the app, it’ll work as expected and shown below.

Expected output

So what exactly changed behind the scenes?

The basic funda still remains the same for the Widget and Element trees. But now as we’ve provided unique keys to each widget, the Element tree will also check for the Key along with the Type as shown below.

Finally, our widgets are reordered correctly with their individual states.

Types Of Keys

Global Key

This key is used when we’ve a widget that is shared across screens and we want to maintain the same state for it.

For example, a switch for light and dark theme. No matter from which screen we changed it, it should remain in the same state.

Another instance could be that we want to find out the position of a widget in the scroll view.

In such cases, we can use Global key.

Value Key

This key is used when we want to identify widgets locally based on a value. The scope is limited to a parent widget.

Object Key

This key is used when we want to identify widgets and the uniqueness is defined by a combination of different values. In such cases, we use Object key where we pass a complete object as a key identifier.

Unique Key

This key is used when we don’t have any exact criteria for uniqueness for a widget but it can still be unique.

Conclusion

Keys are useful in scenarios where we’re altering the ordering of widgets or some widget needs to maintain its state across screens. Keys are also handy in state management for widgets.

That is all for now! Stay tuned!

Connect with me (if the content is helpful to you ) on

Until next time…

Cheers!

--

--

Flutter Community
Flutter Community

Published in Flutter Community

Articles and Stories from the Flutter Community

Saurabh Pant
Saurabh Pant

Written by Saurabh Pant

App Architect (Native & Flutter) | TataDigital | Mentor | Instructor @Droidcon | Youtube @_zaqua | Writer @Flutter Community

No responses yet