Answer
Overview
The super key in Flutter refers to using the
text
supertext
keyWhat is a Key?
A key is a unique identifier for widgets. It helps Flutter identify which widgets changed, moved, or were removed.
dartclass MyWidget extends StatelessWidget { const MyWidget({Key? key}) : super(key: key); // ^^^^^^^^^^^^^^^^ // This is "super key" }
Why Use super(key: key)?
1. Pass Key to Parent Class
Widgets inherit from
text
StatelessWidgettext
StatefulWidgettext
keydart// StatelessWidget constructor requires key abstract class StatelessWidget extends Widget { const StatelessWidget({Key? key}) : super(key: key); } // Your widget passes key to parent class MyWidget extends StatelessWidget { const MyWidget({Key? key}) : super(key: key); // ^^^^^^^^^^^^^^^^ // Passes key to StatelessWidget }
2. Enable Widget Identification
Keys help Flutter track widgets across rebuilds.
dart// Without key class TodoList extends StatelessWidget { final List<String> todos; const TodoList(this.todos); Widget build(BuildContext context) { return Column( children: todos.map((todo) => TodoItem(todo)).toList(), ); } } // With key class TodoList extends StatelessWidget { final List<String> todos; const TodoList(this.todos, {Key? key}) : super(key: key); Widget build(BuildContext context) { return Column( children: todos .map((todo) => TodoItem( todo, key: ValueKey(todo), // Unique key for each item )) .toList(), ); } }
Types of Keys
1. ValueKey
Use when items have unique values.
dartclass TodoItem extends StatelessWidget { final String todo; const TodoItem(this.todo, {Key? key}) : super(key: key); } // Usage TodoItem('Buy milk', key: ValueKey('Buy milk'))
2. ObjectKey
Use when items are objects.
dartclass User { final int id; final String name; User(this.id, this.name); } UserWidget(user, key: ObjectKey(user))
3. UniqueKey
Use when you need a unique key every time.
dartRandomColorBox(key: UniqueKey())
4. GlobalKey
Access widget state from anywhere.
dartfinal scaffoldKey = GlobalKey<ScaffoldState>(); Scaffold( key: scaffoldKey, body: ..., ) // Access from anywhere scaffoldKey.currentState?.openDrawer();
Complete Example: super(key: key)
dartimport 'package:flutter/material.dart'; // Base widget accepting key class CustomButton extends StatelessWidget { final String text; final VoidCallback onPressed; // Accept key and pass to super const CustomButton({ required this.text, required this.onPressed, Key? key, // Optional key parameter }) : super(key: key); // Pass to parent StatelessWidget Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: Text(text), ); } } // Usage with key class MyScreen extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ CustomButton( text: 'Submit', onPressed: () {}, key: Key('submit_button'), // Assign key ), CustomButton( text: 'Cancel', onPressed: () {}, key: Key('cancel_button'), ), ], ); } }
When Keys Matter
Problem: Widget State Loss
dartclass StatefulCounter extends StatefulWidget { const StatefulCounter({Key? key}) : super(key: key); _StatefulCounterState createState() => _StatefulCounterState(); } class _StatefulCounterState extends State<StatefulCounter> { int count = 0; Widget build(BuildContext context) { return Text('$count'); } } // Without keys - state lost when reordered class CounterList extends StatelessWidget { final List<String> items; const CounterList(this.items); Widget build(BuildContext context) { return Column( children: items.map((item) { return StatefulCounter(); // ❌ No key - state lost }).toList(), ); } }
Solution: Add Keys
dartclass CounterList extends StatelessWidget { final List<String> items; const CounterList(this.items); Widget build(BuildContext context) { return Column( children: items.map((item) { return StatefulCounter( key: ValueKey(item), // ✅ Key preserves state ); }).toList(), ); } }
StatefulWidget with Key
dartclass Counter extends StatefulWidget { final String title; // Accept key and pass to super const Counter({ required this.title, Key? key, }) : super(key: key); _CounterState createState() => _CounterState(); } class _CounterState extends State<Counter> { int _count = 0; Widget build(BuildContext context) { return Column( children: [ Text(widget.title), Text('$_count'), ElevatedButton( onPressed: () => setState(() => _count++), child: Text('Increment'), ), ], ); } } // Usage with key Counter( title: 'My Counter', key: ValueKey('counter_1'), )
GlobalKey Example
dartimport 'package:flutter/material.dart'; class FormScreen extends StatelessWidget { // Create GlobalKey final _formKey = GlobalKey<FormState>(); Widget build(BuildContext context) { return Form( key: _formKey, // Assign GlobalKey child: Column( children: [ TextFormField( validator: (value) { if (value == null || value.isEmpty) { return 'Required'; } return null; }, ), ElevatedButton( onPressed: () { // Access form state via GlobalKey if (_formKey.currentState!.validate()) { print('Form is valid'); } }, child: Text('Submit'), ), ], ), ); } }
const Constructor Requirement
For
text
constdart// ✅ Good - Accepts key class MyWidget extends StatelessWidget { const MyWidget({Key? key}) : super(key: key); Widget build(BuildContext context) => Container(); } // Usage const MyWidget() // Can use const // ❌ Bad - No key parameter class MyWidget extends StatelessWidget { const MyWidget(); // ❌ Cannot be fully const without key Widget build(BuildContext context) => Container(); }
Best Practices
Important: Always include
in custom widget constructorstext{Key? key}
✅ Do
dart// Good - Accept and pass key class CustomWidget extends StatelessWidget { final String title; const CustomWidget({ required this.title, Key? key, }) : super(key: key); } // Good - Use ValueKey for lists ListView.builder( itemBuilder: (context, index) { return ListTile( key: ValueKey(items[index].id), title: Text(items[index].name), ); }, )
❌ Don't
dart// Bad - Missing key parameter class CustomWidget extends StatelessWidget { final String title; const CustomWidget({required this.title}); // Missing: Key? key, super(key: key) } // Bad - Using UniqueKey in build method Widget build(BuildContext context) { return MyWidget(key: UniqueKey()); // ❌ Creates new key every build }
Common Patterns
Pattern 1: Optional Key
dartclass MyWidget extends StatelessWidget { const MyWidget({Key? key}) : super(key: key); } // Usage MyWidget() // No key MyWidget(key: ValueKey('my_widget')) // With key
Pattern 2: Required Key
dartclass MyWidget extends StatelessWidget { const MyWidget({required Key key}) : super(key: key); } // Usage MyWidget(key: ValueKey('my_widget')) // Key required