Moduler route

Moduler route is a powerful route manager that works in a modular way that allows you to create an application with more independent and reusable functionality. And with an integrated dependency injection system, you will have fully decoupled modules.

Moduler

Moduler is a mixin that will be inherited by your main widget and it's the heart of your modules. Here you'll inform your modules and global injections.

void main() => runApp(MyApp());

class MyApp extends StatelessWidget with Moduler {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: initialRoute(() {
        // Some rules to check the initial route
        return "moduler/initial-route"
      }),
      onGenerateRoute: routeTo,
      onUnknownRoute: unknownRoute,
      navigatorObservers: [modulerRouteObserver],
    );
  }

  @override
  List<Module> get modules => [];

  @override
  List<Injector> get globalInjections => [];
}
  • initialRoute(String Function()) a no async closure to check initial route
  • modules list of your modules
  • globalInjections all of your classes that you wanna get from any module

Modules

The idea behind moduler is separate your application in modules. To create a module do like code bellow.

class ExampleModule extends Module {
  @override
  String get path => "module-name";

  @override
  List<ModuleRoute> get routes => [];

  @override
  List<Injector> get injections => [];
}
  • path name of the Module
  • routes all routes that belong to this module
  • injections like globalInjections of the Moduler, but only accessible to module routes

Routes

To pass views to your module you must have to create a ModuleRoute.

ModuleRoute(
  path: "route-name",
  builder: (arguments) => View(),
  transitionType: RouteTransitionType.material
);
  • path name of the ModuleRoute. If the view is the "home" (first view) of module. You may call it "/"
  • builder a closure where you return your view. builder have a Object as argument and it is the parameter passed to your route
  • transitionType Moduler route uses page_transition to implement a lot of page transitions in addition to CupertinoPageRoute and MaterialPageRoute. So you have 12 page transitions

Call route

You just user Navigator or any other navigation lib to navigate.

Navigator.of(context).pushNamed(
  "module-name/route-name",
  arguments: "Passing parameters"
);

To navigate between modules/routes you have to follow some rules:

  • Every time you'll navigate to a new module, you need to inform the module name.
  • If you have a route named "/" in a module and called Navigator.of(context).pushNamed("module-name"); or Navigator.of(context).pushNamed("module-name/"); it will always call that ModuleRoute
  • If you already at navigating in a module, you don't need any more to pass a module name. Just pass the route name for navigate inside the module Navigator.of(context).pushNamed("second-route-name");

Dependency Injection

How I said before _ Modular route _ have a powerful dependency injection system. First you have to inform to your Module or Moduler what class will be injected. for that use Injector.

Injector<MyController>(
  inject: (arguments) => MyController(_user),
);

CAUTION!! You always have to pass the type to Injector.

Injector have a closure that have an Object as parameter. The arguments is the same passed to builder closure of the ModuleRoute. And returns a class of the same type you have informed before.

To get the injected class you will use Inject

final _controller = Inject.instance<MyController>();

Inject have two static methods to get objects:

  • instance return always a new instance of a object
  • get return an existing instance. If the object is not instantiated, it'll be create

And two more for remove the singletons only:

To dispose a Inject.get<MyController>(); injection. Just di this.

  • dispose remove only a specific object instance
  • reset remove all singletons

IMPORTANTE!!

When uses get, the singleton will be alive only during navigation in a module. Unless it was injected on globalInjections in Moduler

Mocking for unit test

Inject have a special method to using in tests called mock. Just pass the mocked class with the type class.

final controllerMock = MyControllerMock();
Inject.mock<MyController>(controllerMock);

If having any questions, see our example to better understanding! Or send us an e-mail :grin:

My spacial thanks to Elton Morais for testing and improve some features

Libraries

moduler_route