Scenario
I would need to conditionally navigate to a screen and hence was using WillPopScope
widget wrapped around the Scaffold
widget in my app.
Code:
WillPopScope(
onWillPop: () async {
if (hasProfilePicUpdated) {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.dashboard,
(route) => false,
arguments: DashboardArgumentModel(
onboardingState: dashboardArgumentModel.onboardingState,
).toMap(),
);
} else {
Navigator.pop(context);
}
return false;
},
child: Scaffold(
With the code above, I was able to navigate to my desired screen. Now after I upgraded Flutter to 3.16.1, I got a warning that WillPopScope
is deprecated and that I should use PopScope
. Hence, I updated my code to as below:
Code:
PopScope(
// canPop: true, - this makes no difference
onPopInvoked: (val) async {
if (hasProfilePicUpdated) {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.dashboard,
(route) => false,
arguments: DashboardArgumentModel(
onboardingState: dashboardArgumentModel.onboardingState,
).toMap(),
);
} else {
Navigator.pop(context);
}
},
child: Scaffold(
Issue:
However, the code using PopScope gives me the following error when I click on the back button:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: ‘package:flutter/src/widgets/navigator.dart’: Failed assertion: line 5238 pos 12: ‘!_debugLocked’: is not true.
I have tried
- wrapping the
Navigator.pop(context)
in aWidgetsBinding.instance.addPostFrameCallback((_)
- adding a
Future.delayed()
beforeNavigator.pop(context)
but keep facing the same issue.
Request:
I would like to know what I’m doing wrong in my code which is preventing me from implementing the desired behaviour using PopScope and how to rectify the error.
2
Answers
Based on the answer given at: https://stackoverflow.com/a/77529346/19413610
it turns out that I needed to return from the function if the boolean parameter to the onPopInvoked function returns true. Below is the functioning code:
You can use the SchedulerBinding.instance.addPostFrameCallback() method to delay the call to Navigator.pop() until after the current frame has been rendered.