Skip to content

prefer_extracting_callbacks

v1.0.0WarningConfigurableWidget Best Practices

This rule flags a widget’s callback argument holding a long inline closure.

This rule is in the pedantic preset: it imposes an architecture rather than catching a defect.

A closure written inline inside build puts logic in the middle of a layout description, where it is read by everyone scanning for the tree’s shape and re-created on every rebuild. Extracting it to a method leaves the tree readable and gives the behaviour a name.

The threshold is what makes the rule usable: onTap: () => _submit() is a tear-off in all but spelling, and reporting it would be noise. Only closures whose body exceeds max_statements (default 3) report.

A builder argument is exempt by default. Its whole job is to describe a subtree, so extracting it to a method would trip avoid_returning_widgets instead — the two rules would otherwise disagree about the same code.

Not to be confused with avoid_returning_widgets, which is about a function returning a widget. This one is about behaviour attached to one.

See also: Flutter: performance best practices

final button = ElevatedButton(
onPressed: () {
print('validating');
print('saving');
print('closing');
print('done');
},
child: const Text('Save'),
);
void _save() {
print('validating');
print('saving');
print('closing');
print('done');
}
// The tree stays readable and the behaviour has a name.
final button = ElevatedButton(
onPressed: _save,
child: const Text('Save'),
);
// A short closure is a tear-off in all but spelling — never reported.
final shortButton = ElevatedButton(
onPressed: () => print('save'),
child: const Text('Save'),
);
analysis_options.yaml
many_lints:
rules:
prefer_extracting_callbacks:
max_statements: 3
additional_ignored_parameters: [contentBuilder]
Option Type Default Description
max_statements int 3 Longest inline closure body that is left alone
ignored_parameters list of strings [builder, itemBuilder, separatorBuilder] Named parameters whose closures describe a subtree rather than behaviour
additional_ignored_parameters list of strings [] Names to add to that list
report_functions bool false Apply the same budget to ordinary function calls, not just widget constructors

report_functions covers what is sometimes shipped as a separate prefer-extracting-function-callbacks rule — it is this one with the widget requirement dropped. It is off by default because outside a widget tree the argument is much weaker: a long closure passed to compute or a stream transform is often exactly where the logic belongs, and there is no layout description for it to interrupt.

To disable this rule:

many_lints.yaml
rules:
prefer_extracting_callbacks: false

To keep the rule on but skip certain paths, use per-rule exclude.