Added a generic type to the `PopScope` class and replaced the `onPopInvoked` with a new method `onPopInvokedWithResult`. The new method takes a boolean `didPop` and a `result` as position parameters.
Original behavior
Previously, `PopScope` didn't have a way to access the pop result when `onPopInvoked` was called. The generic type is added to the `PopScope` class so that the new method `onPopInvokedWithResult` can access the type-safe result.
New behavior
Added a generic type (`<T>`) to the `PopScope` class and a new method `onPopInvokedWithResult`. The `onPopInvoked` property was deprecated in favor of `onPopInvokedWithResult`.
- Who is affected
- Applications and packages relying on the previous behaviour or signature. Code that uses PopScope, Form.onPopInvoked, Form.onPopInvokedWithResult and related APIs.
- Practical impact
- Behaviour or API differences that can break builds or change runtime behaviour.
- What action should I take?
- Follow the official migration guide below, update affected call sites, run `dart fix --apply` where a fix is available, then run your tests.
Before and after (from the official guide)
| 1 | import 'package:material_ui/material_ui.dart'; | |
| 2 | ||
| 3 | void main() { | |
| 4 | runApp( | |
| 5 | MaterialApp( | |
| 6 | navigatorKey: nav, | |
| 7 | home: Column( | |
| 8 | children: [ | |
| 9 | Form( | |
| 10 | canPop: false, | |
| 11 | − | onPopInvoked: (bool didPop) { |
| 12 | if (didPop) { | |
| 13 | return; | |
| 14 | } | |
| 15 | launchConfirmationDialog(); | |
| 16 | }, | |
| 17 | child: MyWidget(), | |
| 18 | ), | |
| 19 | − | PopScope( |
| 20 | canPop: false, | |
| 21 | − | onPopInvoked: (bool didPop) { |
| 22 | if (didPop) { | |
| 23 | return; | |
| 24 | } | |
| 25 | launchConfirmationDialog(); | |
| 26 | }, | |
| 27 | child: MyWidget(), | |
| 28 | ), | |
| 29 | ], | |
| 30 | ), | |
| 31 | ), | |
| 32 | ); | |
| 33 | } |
| 1 | import 'package:material_ui/material_ui.dart'; | |
| 2 | ||
| 3 | void main() { | |
| 4 | runApp( | |
| 5 | MaterialApp( | |
| 6 | navigatorKey: nav, | |
| 7 | home: Column( | |
| 8 | children: [ | |
| 9 | Form( | |
| 10 | canPop: false, | |
| 11 | + | onPopInvokedWithResult: (bool didPop, Object? result) { |
| 12 | if (didPop) { | |
| 13 | return; | |
| 14 | } | |
| 15 | launchConfirmationDialog(); | |
| 16 | }, | |
| 17 | child: MyWidget(), | |
| 18 | ), | |
| 19 | + | PopScope<Object?>( |
| 20 | canPop: false, | |
| 21 | + | onPopInvokedWithResult: (bool didPop, Object? result) { |
| 22 | if (didPop) { | |
| 23 | return; | |
| 24 | } | |
| 25 | launchConfirmationDialog(); | |
| 26 | }, | |
| 27 | child: MyWidget(), | |
| 28 | ), | |
| 29 | ], | |
| 30 | ), | |
| 31 | ), | |
| 32 | ); | |
| 33 | } |
Raw before / after
import 'package:material_ui/material_ui.dart';
void main() {
runApp(
MaterialApp(
navigatorKey: nav,
home: Column(
children: [
Form(
canPop: false,
onPopInvoked: (bool didPop) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
PopScope(
canPop: false,
onPopInvoked: (bool didPop) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
],
),
),
);
}import 'package:material_ui/material_ui.dart';
void main() {
runApp(
MaterialApp(
navigatorKey: nav,
home: Column(
children: [
Form(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
PopScope<Object?>(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
],
),
),
);
}Official migration guide (excerpt, © The Flutter Authors, CC BY 3.0)
Code before migration:
import 'package:material_ui/material_ui.dart';
void main() {
runApp(
MaterialApp(
navigatorKey: nav,
home: Column(
children: [
Form(
canPop: false,
onPopInvoked: (bool didPop) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
PopScope(
canPop: false,
onPopInvoked: (bool didPop) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
],
),
),
);
}Code after migration:
import 'package:material_ui/material_ui.dart';
void main() {
runApp(
MaterialApp(
navigatorKey: nav,
home: Column(
children: [
Form(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
PopScope<Object?>(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (didPop) {
return;
}
launchConfirmationDialog();
},
child: MyWidget(),
),
],
),
),
);
}The generic type should match the generic type of the [Route][]
that the PopScope is in.
For example, if the route uses int as its generic type,
consider using PopScope<int>.
If the PopScope widgets are shared across multiple routes with
different types, you can use PopScope<Object?> to catch all possible types.
AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.Listed in the official breaking-changes index (docs.flutter.dev/release/breaking-changes).
An official announcement or migration guide documents an intended behaviour or API change. A verified source change (git diff) shows code changed but does not by itself prove a public API is breaking. AI interpretations are labelled and never used to classify a change.
- Official migration guide
- PopScope
- onPopInvoked
- Route
- onPopInvokedWithResult
- Form.onPopInvoked
- Form.onPopInvokedWithResult
- Issue 137458
- Add generic type for result in PopScope
- Reapply new PopScope API
- Source commit
- b3045439b7c0
- Source last updated
- Oct 21, 2026
- Last synchronized
- Oct 21, 2026
- Publication status
- published
Publication history
- Oct 21, 2026, 8:31 PM: new → published (ingestion) — Backed by an official breaking-change/migration guide.
AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.