I've programmed an application that requires authentication. I also saved persistent authentication data on the device safely so a manual login is not required every time the app starts.

As soon as the app starts, it automatically routes to the main Route (in my case, that is a stateless splash-screen). The following code gets executed:

  @override
  Widget build(BuildContext context) {
        ifLoggedIn(context);
      return Scaffold(
          body: Center(
              child: Image.asset("assets/logo-sm.png", width: 200,),
          ),
      );
  }
    void ifLoggedIn(context) async {
        if (User.user != null) { // in case of a hot reload resetting the damn app
            Navigator.of(context).push(right(PublicStart()));
        } else {
            User user = await User.loginFromSafeStorage(context); // login from safe storage
            if (user != null)
                Navigator.of(context).push(right(PublicStart()));
            else // nope, no credentials found, redirect to the start-screen
                Navigator.of(context).push(up(SignInScreen()));
        }
    }

the ifLoggedIn(context) function is an asynchronous function that checks whether or not login data has already been stored locally. If this is the case, it will authenticate the user.

This process is as follows:

Case: Logindata found -> Login user and navigate to the start-screen
Case: No logindata found -> Navigate to the sign-in-screen.

As you can see, since this function is asynchronous, the Scaffold below is returned and the build process of that stateless widget isn't interrupted. But...

apparantly, a setState was called during the build of this widget. I don't know how or why, but it seems to happen. I've tried fixing this problem but this isn't the first time it occurs and I am having a bad feeling that I am applying bad practices in the development of this app.

I suspect that it has something to do with the check for a logged in user.

Another error that I get a lot (and I mean, really A LOT) at random times is the following: Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line <insert number> pos <insert number>: '!_debugLocked': is not true. where the numbers vary from time to time. As I understand this, it's to prevent routes from getting called multiple times or disrupting anything that has to do with the routing. Since I get this error at random times, this must have something to do with asynchronous functions.

To finalise my question: What am I doing wrong here and what is the norm to do the above?


Solution 1: Haidar

Edit(more clarification):

The asynchronous calls must not be fired from build method as it(the build method) can be called alot of times for different reasons and so you don't want your code to execute multiple times as this will cause undesired results

the solution is to use a stateful widget and do the code that must run once (in your case the code that checks auth status) from there(from initState() preferrably)

also take a look at this answer