'Flutter-How do I switch from login screen to home and back? Back-end works but can't show screen without manually refresh

1.this is the main entry

void main()  {
    WidgetsFlutterBinding.ensureInitialized();
    StorageUtil.getInstance();
     runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Wrapper(),
    );
  }
}
  1. This is the Wrapper. The log-in form or the home page do not show unless I manually hot-reload the app. I've tried everything but i am stuck. Please help.
class Wrapper extends StatefulWidget {

  @override
  _WrapperState createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
  User _user = User();

  @override
  Widget build(BuildContext context) {
    _user.uId = StorageUtil.getString('access_token');
    if(_user.uId != null && _user.uId != ""){
      print('filled ${_user.uId}');
        return Home();
    }else{
      print('empty ${_user.uId}');
        return Authenticate();
    }
  }
}


Solution 1:[1]

I think your StorageUtil is giving you promise for get data back to you but you are not waiting for it when app loads at first time.You can try await StorageUtil.getInstance(); in main block.

void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await StorageUtil.getInstance();
    runApp(MaterialApp(home: MyApp()));
}

Solution 2:[2]

You need to watch the instance. Right now you are grabbing the instance to get the value but you are not subscribing to the value itself, which means that when the value changes nothing will happen until you refresh the page. I recommend subscribing to the value (access_token) that is determining the login screen vs the home screen.

Flutter has some built in features that makes this a bit easier such as streams and or quicker widgets like the ValueListenerBuilder. Let's see if we can do that with StorageUtil.

void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await StorageUtil.getInstance();
    runApp(MaterialApp(home: MyApp()));
}

class Wrapper extends StatefulWidget {

  @override
  _WrapperState createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
  User _user = User();

  @override
  Widget build(BuildContext context) {
    
    return ValueListenableBuilder(
      valueListenable: StorageUtil.getString('access_token');,
      builder: (BuildContext context, String value, _) {
        if(value != null && value != ""){
          print('filled ${_user.uId}');
          return Home();
        } else {
          print('empty ${_user.uId}');
          return Authenticate();
        }
      },
    ),
  }
}

It is rough but it should get the job done! I recommend probably finding a more streamlined way to store your state than just the StorageUtil that'll better scale as your application grows.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nisarg
Solution 2 Francesco Hayes