Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way seperate the routing of different modules in my flutter app

Right now Im using generated routing. I have a class that returns all my routes to the onGenerateRoute. I have several modules in my app, which i have seperated. Accessible modules depend on the type of user. Im trying to create a different routes file for each module and have access to them from the main routes file. I am using bloc state management. (my routes file is starting to get really cluttered.)

like image 342
nuiji Avatar asked Sep 17 '25 20:09

nuiji


2 Answers

One way I've done it is via nested navigation and using multiple Navigator widgets, each of which manages a group of routes (this is if you're using Navigator 1.0).

For example; in the main routes object, you can have the routes to each module widget: User and Admin:

routes: {
   '/user': (context) => UserWidget(),
   '/admin': (context) => AdminWidget()
}

Then inside each of these widgets (which define your separate modules) you can have a nested Navigator widget that lays out the routes for each module (some "pseudo" code to get the idea):

class AdminWidget 
- Navigator
   - onGenerateRoute
     - '/admin_page1'
     - '/admin_page2'
     - '/admin_page3'
class UserWidget 
- Navigator
  - onGenerateRoute
    - '/user_page1'
    - '/user_page2'
    - '/user_page3'

That way you can group your routes and direct users to the corresponding routes based on their type or role. This is one way to do it.

like image 124
Roman Jaquez Avatar answered Sep 19 '25 10:09

Roman Jaquez


What you should do is create a router for each module and register these routers in the main router.

In your main router, you register the module routers.

Here's how I did mine:

App Router:

class AppRouter {
  AppRouter._();
  static final _instance = AppRouter._();
  factory AppRouter() => _instance;

  final _moduleRouterRegistration = <SubRouter>[
    moduleARouter,
    moduleBRouter,
  ];

  Route onGenerateRoute(RouteSettings settings) {
    final routeComponents = settings.name!.split(' ');
    //Backward compatibility check
    if (routeComponents.length == 1) {
      return MainAppRouter.generateRoutes(settings);
    }

    final module = _moduleRouterRegistration.firstWhere(
      (subRouter) => subRouter.moduleName == routeComponents[0],
      orElse: () => throw Exception(
        'Module with name ${routeComponents[0]} not registered in Router',
      ),
    );
    final routeName = routeComponents[1];
    final splitRouteSettings = RouteSettings(
      name: routeName,
      arguments: settings.arguments,
    );
    return Platform.isIOS
        ? CupertinoPageRoute(
            builder: (_) => module.router(splitRouteSettings),
            settings: splitRouteSettings,
          )
        : MaterialPageRoute(
            builder: (_) => module.router(splitRouteSettings),
            settings: splitRouteSettings,
          );
  }
}

Main/Existing Router:

abstract class MainAppRouter {
  static Route<dynamic> generateRoutes(RouteSettings settings) {
    switch (settings.name) {
      case dashboardRoute:
        return getPageRoute(
          settings: settings,
          view: const MyHomePage(),
        );
      case normalARoute:
        return getPageRoute(
          settings: settings,
          view: const NormalA(),
        );
      case normalBRoute:
        return getPageRoute(
          settings: settings,
          view: const NormalB(),
        );
      default:
        return getPageRoute(
          settings: settings,
          view: Scaffold(
            body: Center(
              child: Text('No route defined for ${settings.name}'),
            ),
          ),
        );
    }
  }

  static PageRoute<dynamic> getPageRoute({
    required RouteSettings settings,
    required Widget view,
  }) {
    return Platform.isIOS
        ? CupertinoPageRoute(settings: settings, builder: (_) => view)
        : MaterialPageRoute(settings: settings, builder: (_) => view);
  }
}

Sub router interface:

abstract class SubRouter {
  String get moduleName;
  Widget router(RouteSettings settings);
}

Sub router:

final moduleARouter = _ModuleARouter();

class _ModuleARouter implements SubRouter {
  @override
  String get moduleName => 'moduleA';

  @override
  Widget router(RouteSettings settings) {
    switch (settings.name) {
      case aOneRoute:
        return ViewAOne();
      case aTwoRoute:
        return const ViewATwo();
      case aThreeRoute:
        return ViewAThree();
      default:
        return const Scaffold(
          body: Center(
            child: Text(
              'Cannot find route',
            ),
          ),
        );
    }
  }
}

AppRouter().onGenerateRoute is registered as the onGenerateRoute method of the material app.

You could check the github repo for a working sample https://github.com/mastersam07/s-p-h-r-

like image 32
Codefarmer Avatar answered Sep 19 '25 10:09

Codefarmer