23

I'm trying to detect that user is no longer authenticated and redirect user to login. This is how I'm doing it

  Widget build(BuildContext context) {
    return FutureBuilder(
        future: _getData(context),
        builder: (context, snapshot) {
          try {
            if (snapshot.hasError && _isAuthenticationError(snapshot.error)) {
                Navigator.push(context, MaterialPageRoute(builder: (context) => LoginView()));
            }

Unfortunately doing navigation on build is not working. It throws this error

flutter: setState() or markNeedsBuild() called during build.
flutter: This Overlay widget cannot be marked as needing to build because the framework is already in the
flutter: process of building widgets.  A widget can be marked as needing to be built during the build 

I cannot just return LoginView widget since parent widget containts app bar and floating button and login view needs to be displayed without these controlls.. I need to navigate.

Is it possible to do it?

StackOverflower
  • 5,463
  • 13
  • 58
  • 89

3 Answers3

54

Wrap it in Future.microtask. This will schedule it to happen on the next async task cycle (i.e. after build is complete).

Future.microtask(() => Navigator.push(
  context, 
  MaterialPageRoute(builder: (context) => LoginView())
));
Abion47
  • 22,211
  • 4
  • 65
  • 88
  • But in this case, I am having an endless loop. Are there any other ways you can do that? – Valary o May 07 '20 at 19:28
  • 1
    @Valaryo `Future.microtask` only fires once, so a loop is impossible if you are doing it right. The only way I can imagine this causing an endless loop is if you are using it to navigate to the page that you are already on and loading the page is what triggers the navigation. There could also be an issue where if you are trying to navigate during the `build` method and the widget is rebuilding many times, you will continue to queue up navigations after the first one already triggered. (This is why doing non-UI stuff in the `build` method is generally a bad idea.) – Abion47 May 07 '20 at 19:39
  • yeah, apparently I am indeed doing that wrong. I am more than sure about that at the moment. I am just getting into the way of things with Flutter. I've tried all possible ways to accomplish that but I either have an error related to SetState or something with that or something with MediaQuery. In short, I've got a wrapper which holds three components: header, footer and a viewWrapper (with a page view). And here you are right. I am scrolling through the pages and my last page is a Login Widget, but having reached it I want to get out of the pageView mode (where I have footer and header) – Valary o May 07 '20 at 19:46
  • so I then try to redirect to a Login page to have it fullscreen and kinda static. But my login is not on Login page but I already tried to put in inside footer and the top-level wrapper. – Valary o May 07 '20 at 19:48
  • I use Provider to watch the state. Do you have any ideas on how I can solve it? – Valary o May 07 '20 at 19:50
  • I've moved the login into my viewWrapper and it did work. Just wanted to thank you for help – Valary o May 07 '20 at 21:02
  • Thank you. This works great! – Jeremi Dec 29 '21 at 18:19
0

Streams in flutter

The usual thing is to use a flow where user changes occur. When the user logs off, he detects that change and can direct it to another window.

Konstantin Kozirev
  • 944
  • 1
  • 10
  • 23
DomingoMG
  • 1,827
  • 2
  • 23
  • 44
-3

problem here :

snapshot.hasError && _isAuthenticationError(snapshot.error)

Instead of this use OR

snapshot.hasError || _isAuthenticationError(snapshot.error)
Roshin Raphel
  • 2,612
  • 4
  • 22
  • 40