7

I'm trying to make my flutter architecture as best as possible before diving into the features of my app. I have already made an app with firebase Authentification working, based on ChangeNotifierProvider :

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      builder: (_) => AuthentService.instance(),
      child: Consumer(builder: (context, AuthentService authentService, _) {
        switch (authentService.status) {
          case Status.Authenticated:
            return DashboardScreen();
          default:
            return LoginScreen();
        }
      }),
    );
  }
}

This Home widget is listening to the authentication status and return any of the LoginScreen or DashboardScreen widget if logged in or not. The LoginScreen can update the status of the service if the user logs in. The DashboardScreen also can modify the status by logging out. Then due to this Notifier, the widget rendered is switching beetween the two screens.

I am trying to add generated routes to this working part, in order to make my app more 'standard'. I have defined some routes into a Router class :

class Router {
  static const String homeRoute = '/';
  static const String loginRoute = '/login';
  static const String dashboardRoute = '/dashboard';

  static Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case homeRoute:
        return MaterialPageRoute(builder: (_) => Home());
      case loginRoute:
        return MaterialPageRoute(builder: (_) => LoginScreen());
      case dashboardRoute:
        return MaterialPageRoute(builder: (_) => DashboardScreen());
    }
  }
}

I can now modify my MyApp widget :

onGenerateRoute: Router.generateRoute,
initialRoute: Router.homeRoute,

The question is : How I can make this routing working in the Home widget ?? Actually, i make a switch on the status of my Provided service, and return one of the good widget. Something like choosing a route inside this switch :

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      builder: (_) => AuthentService.instance(),
      child: Consumer(builder: (context, AuthentService authentService, _) {
        switch (authentService.status) {
          case Status.Authenticated:
            return DashboardScreen();
          default:
            return LoginScreen();
        }
      }),
    );
  }
}

How can i use the navigator? I can't use Navigator.pushNamed inside the switch. It needs to return a Widget. Maybe I am wrong this maybe more simple if the LoginScreen should handle the navigation if the login is succesfull? This way the Home widget can render directly the LoginScreen. Is that the best way todo ?

I am trying to make the best architecture possible to start with a clean and well designed app.

Thank you for your help.

jtetrel
  • 93
  • 6
  • Hello, welcome to StackOverflow. You have given a lot of information, but not much clarity on your question. Can you please be a bit more specific on what your problem is? – J. S. Dec 28 '19 at 01:58
  • Hello. Thanks. I tried to be more precise abnout my question. Is it Ok like that? – jtetrel Dec 28 '19 at 09:47
  • "How I can make this routing working in the Home widget ?" Is a bit confusing. Are you getting an error? Can you share it with us? – J. S. Dec 28 '19 at 12:43
  • did you find a solution? – Martin May 31 '21 at 17:11
  • you have to share the same object of each ```ChangeNotifier``` class. I haven't figured it out completely. Check this one https://stackoverflow.com/questions/59576495/flutter-provider-nested-navigation – Panagiss May 28 '22 at 21:28

1 Answers1

0

If you'd like to add a Navigator inside Widget build(), you can use Future.microtask. This should schedule the task after the build cycle.

Future.microtask(() => Navigator.push(
  context, 
  MaterialPageRoute(builder: (context) => LoginScreen())
));
Omatt
  • 8,564
  • 2
  • 42
  • 144