Let’s understand the concept of Flutter’s key.

Parth Bhanderi
3 min readJul 10, 2023

--

The term “key” in Flutter refers to an identification given to a widget in order to identify it specifically. Keys are essential for managing widget state, effectively updating the user interface, and maintaining widget state throughout rebuilds. Here are several essential ideas about keys in Flutter, along with some illustrations:

  1. GlobalKey:

A widget can only be identified by a “GlobalKey” across the whole application. It is frequently used when you need to call methods on a child widget or access the state of a particular widget from other areas of your program.

— An example

GlobalKey<MyWidgetState> myWidgetKey = GlobalKey<MyWidgetState>();

// Using the GlobalKey to access the state of MyWidget
myWidgetKey.currentState?.someMethod();

2. ValueKey:

A widget is identified by a “ValueKey” key based on its value rather than its identity. When working with lists or collections of widgets, where the key distinguishes between various objects based on a certain value, it is frequently employed.

— An example

List<String> items = ['Apple', 'Banana', 'Orange'];
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index]), // Using ValueKey with item value
title: Text(items[index]),
);
},
);

3. ObjectKey:

An ‘ObjectKey’ is a key that distinguishes a widget depending on the identification of an object. It is helpful when a widget changes its characteristics while keeping its identity (for instance, when a widget is regenerated with new data).

— An example

Widget build(BuildContext context) {
final MyData data = getDataFromSomewhere();

return ObjectKey(
data, // Using ObjectKey with data object
child: MyWidget(data: data),
);
}

4. UniqueKey:

‘UniqueKey’ refers to a key that ensures exclusivity among all other keys used in the same build environment. When you need to rebuild a widget completely, making sure it does not have the same identity as any other widget, you usually use this technique.

— An example

Widget build(BuildContext context) {
return Container(
key: UniqueKey(), // Using UniqueKey to force recreation of the widget
child: // …
);
}

These are some of the essential Flutter kinds that provide efficient widget management and identification. You can manage widget state, optimize widget updates, and ensure proper widget behavior in your Flutter applications by utilizing the right keys.

Here is a comprehensive illustration of how keys are used in Flutter:

import 'package:flutter/material.dart';

class Note {
final String id;
final String text;

Note({required this.id, required this.text});
}

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget {
const MyApp({super.key});

@override
MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final List<Note> _notes = [];

void _addNote() {
if (!_formKey.currentState!.validate()) {
return;
}

_formKey.currentState!.save();

setState(() {
final newNote = Note(
id: DateTime.now().toString(),
text: _textController.text,
);
_notes.add(newNote);
_textController.clear();
});
}

void _deleteNote(String id) {
setState(() {
_notes.removeWhere((note) => note.id == id);
});
}

final TextEditingController _textController = TextEditingController();

@override
void dispose() {
_textController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Note Taking App',
home: Scaffold(
appBar: AppBar(title: const Text('Note Taking App')),
body: Column(
children: [
Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _textController,
decoration: const InputDecoration(labelText: 'Enter a note'),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a note';
}
return null;
},
),
),
),
ElevatedButton(
onPressed: _addNote,
child: const Text('Add Note'),
),
Expanded(
child: ListView.builder(
itemCount: _notes.length,
itemBuilder: (context, index) {
final note = _notes[index];
return Dismissible(
key: Key(note.id),
onDismissed: (_) => _deleteNote(note.id),
child: ListTile(
title: Text(note.text),
),
);
},
),
),
],
),
),
);
}
}

In this illustration, a Note with an id and text is represented by the Note class. The primary application widget is represented by the MyAppwidget. When adding a new note, we check and store the form input using a GlobalKey<FormState> . The notes are stored in the _notes list, and their list is shown using a ListView.builder.

When adding a note, we use the DateTime.now() value to create a uniqueid and save it as the Dismissible widget’s Key. When a note is swiped away, this enables us to erase it using its id.

Flutter effectively tracks and manages individual note items with the use of keys. It makes sure that the right state is kept when anything is rebuilt or removed from the list.

Enjoy your coding!!!…

--

--

Parth Bhanderi

Flutter | Dart Virtuoso!!! Go where your energy is appreciated!