How to intercept Navigator.pop and block navigation back conditionally?

Viewed 1050

I'm looking for a way to intercept navigation back conditionally.

User/server can modify global state of the app like authentication, causing page to navigate to login form, but when user navigates to screen A then presses back button twice, user is still able to see widgets that are supposed to be available only for logged in session.

I've tried all I could thought of:

  • onGenerateRoute in MaterialApp but it's not triggered when back button is pressed
  • WillPop is a solution to that, but all top-level widgets would have to be wrapped in it and I need to remember to pass auth state to all the widgets, it's not really scalable solution, but could work
  • navigatorObservers is notified about Navigator.pop events seems not to be able to prevent navigation

Ideally, would like to avoid 3rd party dependencies with hooks on every widget like back_button_interceptor.

It should also work with statelesswidgets, where dispose() method is not available.

Is there any way to get something like single class/point of failure "navigator interceptor" which would return true/false and be able to modify route in flight based on a condition?

1 Answers

Looking into the implementation of WillPopScope, it makes use of the addScopedWillPopCallback() function of the ModalRoute.

https://api.flutter.dev/flutter/widgets/ModalRoute/addScopedWillPopCallback.html

If you implemented a router with onGenerateRoute it should be possible to add an universal check for every route you push. Maybe you could even make a customized Route class inherited from MaterialPageRoute that includes that logic.

If i understood your problem right,i feel like intercepting back navigation is the wrong approach. I would rather try to remove the unauthorized pages from the navigation stack when navigating back to the login screen with Navigator.pushNamedAndRemoveUntil()

Related