proper_super_calls
Warns when super lifecycle methods are called in the wrong order in State subclasses. Methods like initState, didUpdateWidget, activate, didChangeDependencies, and reassemble must call super first. Methods like deactivate and dispose must call super last.
Why use this rule
Section titled “Why use this rule”Flutter’s State lifecycle methods have a specific contract about when super should be called. Calling super.initState() after your own initialization code can lead to errors because the framework expects to set up its own state first. Conversely, calling super.dispose() before your cleanup code means your resources are released while the framework has already torn down its own state. The quick fix automatically moves the super call to the correct position.
See also: State.initState | State.dispose
class _BadInitStateState extends State<BadInitState> { String _data = '';
@override void initState() { _data = 'Hello'; // super.initState() should come before this super.initState(); }
@override Widget build(BuildContext context) => const SizedBox();}
class _BadDisposeState extends State<BadDispose> { @override void dispose() { super.dispose(); // super.dispose() should come after cleanup debugPrint('cleanup'); }
@override Widget build(BuildContext context) => const SizedBox();}
class _BadDeactivateState extends State<BadDeactivate> { @override void deactivate() { super.deactivate(); // super.deactivate() should come after cleanup debugPrint('deactivating'); }
@override Widget build(BuildContext context) => const SizedBox();}class _GoodInitStateState extends State<GoodInitState> { String _data = '';
@override void initState() { super.initState(); // First _data = 'Hello'; }
@override Widget build(BuildContext context) => const SizedBox();}
class _GoodDisposeState extends State<GoodDispose> { @override void dispose() { debugPrint('cleanup'); super.dispose(); // Last }
@override Widget build(BuildContext context) => const SizedBox();}
class _GoodDeactivateState extends State<GoodDeactivate> { @override void deactivate() { debugPrint('deactivating'); super.deactivate(); // Last }
@override Widget build(BuildContext context) => const SizedBox();}Turning this rule off
Section titled “Turning this rule off”This rule is in the recommended preset, so it is on with
preset: recommended or preset: opinionated. Add it to preset: core with
proper_super_calls: true.
To turn it off:
rules: proper_super_calls: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Options
Section titled “Options”Projects with a state abstraction that does not extend Flutter’s State can
opt that base class into this rule:
many_lints: rules: proper_super_calls: state_base_classes: [AppState]rules: proper_super_calls: state_base_classes: [AppState]| Option | Type | Default | Description |
|---|---|---|---|
state_base_classes |
list of strings | [] |
Additional non-State base classes whose subclasses should be treated as state classes |
Related rules
Section titled “Related rules”avoid_cascade_after_if_null— Detect cascades after if-null operators without parentheses.avoid_collapsible_if— Merge nested if statements with &&.avoid_constant_conditions— Detect comparisons where both sides are constants.avoid_constant_switches— Detect switch statements on constant expressions.