get_modular 0.5.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 76

Get Modular #

Read this in other languages: English, Brazilian Portuguese. A flutter_modular fork To support Get natively.

What is Flutter Modular? #

When a project is getting bigger and more complex, we unfortunately end up joining a lot of archives in just one, it makes harder the code maintenance and reusability too. The Modular give us a bunch of adapted solutions for Flutter, such a dependency injection, routes controller and a "Disposable Singletons" System(When a code provider call automatically dispose and clear the injection). The Modular came up prepared for adapt to any state management approach to its smart injection system, managing the memory use of your application.

What is Get? #

Get is a Flutter route manager that is capable of navigating routes, showing snackbars and opening dialogs/bottomsheets from anywhere in the code without needing context. Get also has considerable performance improvements compared to the standard route.

Modular Structure #

Modular gives us a structure that allows us to manage dependency injection and routes in just one file per module, so we can organize our files with that in mind. When all pages, controllers, blocs (and so on) are in a folder and recognized by this main file, we call this a module, as it will provide us with easy maintainability and especially the TOTAL decoupling of code for reuse in other projects.

Modular Pillars #

Here are our main focuses with this package.

  • Automatic Memory Management.
  • Dependency Injection.
  • Dynamic Routes Control.
  • Modularization of Code.

Example #

Getting started with Modular #

Installation #

Open pubspec.yaml of your Project and type:


or install directly from Git to try out new features and fixes:


Using in a New Project #

You need to do some initial setup.

Create a file to be your main widget, thinking of configuring named routes within MaterialApp: (app_widget.dart)

import 'package:flutter/material.dart';
import 'package:get_modular/get_modular.dart';

class AppWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: Modular.navigatorKey,
      initialRoute: "/",
      // add Modular to manage the routing system
      onGenerateRoute: Modular.generateRoute,

Create a file to be your main module: (app_module.dart)

// extends from MainModule
class AppModule extends MainModule {

  // here will be any class you want to inject into your project (eg bloc, dependency)
  List<Bind> get binds => [];

  // here will be the routes of your module or you can navigate by Get.
  List<Router> get routers => [];

// add your main widget here
  Widget get bootstrap => AppWidget();

Finish the configuration in your main.dart file to start Modular.

import 'package:example/app/app_module.dart';
import 'package:flutter/material.dart';
import 'package:get_modular/get_modular.dart';

void main() => runApp(ModularApp(module: AppModule()));

Ready! Your app is already set to Modular!

Adding Routes #

You can add routes to your module using the getter 'routers';

class AppModule extends MainModule {

 // here will be any class you want to inject into your project (eg bloc, dependency)
  List<Bind> get binds => [];

 // here will be the routes of your module
  List<Router> get routers => [
      Router("/", child: (_, args) => HomePage()),
      Router("/login", child: (_, args) => LoginPage()),

  // add your main widget here  
  Widget get bootstrap => AppWidget();

To navigate to a new screen, you can either navigate directly through the widget, or use named routes.;

To return to previous screen you can to use:


To go to the next screen and no option to go back to the previous screen (for use in SplashScreens, login screens and etc.);

To go to the next screen and cancel all previous routes (useful in shopping carts, polls, and exames)

Get.offAll(NextScreen(), (route) => false);
Get.offAllNamed('/nextScreen', (route) => false);

To navigate to the next route, and receive or update data as soon as you return from it:

var data = await;

on other screen, send a data for previous route:

Get.back(result: 'sucess');

So, you can to use:

if(data == 'sucess') madeAnything();

SnackBars #

To show a modern snackbar:

Get.snackbar('Hi', 'i am a modern snackbar');

To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, but with Get, all you have to do is call your Get.snackbar from anywhere in your code or customize it however you want!

               "Hey i'm a Get SnackBar!", // title
               "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message
              icon: Icon(Icons.alarm), 
              shouldIconPulse: true,
              barBlur: 20,
              isDismissible: true,
              duration: Duration(seconds: 3),

  ////////// ALL FEATURES //////////
  //     Color colorText,
  //     Duration duration,
  //     SnackPosition snackPosition,
  //     Widget titleText,
  //     Widget messageText,
  //     Widget icon,
  //     bool shouldIconPulse,
  //     double maxWidth,
  //     EdgeInsets margin,
  //     EdgeInsets padding,
  //     double borderRadius,
  //     Color borderColor,
  //     double borderWidth,
  //     Color backgroundColor,
  //     Color leftBarIndicatorColor,
  //     List<BoxShadow> boxShadows,
  //     Gradient backgroundGradient,
  //     FlatButton mainButton,
  //     OnTap onTap,
  //     bool isDismissible,
  //     bool showProgressIndicator,
  //     AnimationController progressIndicatorController,
  //     Color progressIndicatorBackgroundColor,
  //     Animation<Color> progressIndicatorValueColor,
  //     SnackStyle snackStyle,
  //     Curve forwardAnimationCurve,
  //     Curve reverseAnimationCurve,
  //     Duration animationDuration,
  //     double barBlur,
  //     double overlayBlur,
  //     Color overlayColor,
  //     Form userInputForm

Dialogs #

To open dialog:


To open default dialog:

                title: "My Title",
                content: Text("Hi, it's my dialog"),
                confirm: FlatButton(
                  child: Text("Ok"),
                  onPressed: () => print("OK pressed"),
                cancel: FlatButton(
                  child: Text("Cancel"),
                  onPressed: () => Get.back(),

BottomSheets #

Get.bottomSheet is like showModalBottomSheet, but don't need of context.

      builder: (_){
          return Container(
            child: Wrap(
            children: <Widget>[
            leading: Icon(Icons.music_note),
            title: Text('Music'),
            onTap: () => {}          
            leading: Icon(Icons.videocam),
            title: Text('Video'),
            onTap: () => {},          

Dynamic Routes #

You can use the dynamic route system to pass a value per parameter and get it in your view.

//use (: parameter_name) to use dynamic routes;
//use the args object that is a (ModularArguments) to get the value
  List<Router> get routers => [
      Router("/product/:id", child: (_, args) => Product(id: args.params['id'])),

A dynamic route is considered valid when the value corresponding to the parameter is filled. From this you can use:

Navigator.pushNamed(context, '/product/1'); //args.params['id']) gonna be 1
//or'/product/1'); //args.params['id']) gonna be 1

You can also pass an object using the "arguments" property in the navigation:

Navigator.pushNamed(context, '/product', arguments: ProductModel()); //
//or'/product', arguments: ProductModel()); //

getting on the route

  List<Router> get routers => [
      Router("/product", child: (_, args) => Product(model:,

Route Guard #

We may protect our routes with middleware that will verify that the route is available within a given Route. First create a RouteGuard:

class MyGuard implements RouteGuard {
  bool canActivate(String url) {
    if(url != '/admin'){
      //code of authorization
      return true;
    } else {
      //access denied
      return false

Now put in the 'guards' property of your Router.

  List<Router> get routers => [
        Router("/", module: HomeModule()),
        Router("/admin", module: AdminModule(), guards: [MyGuard()]),

If placed on a module route, RouterGuard will be global to that route.

Route Transition Animation #

You can choose which type of animation you want by setting the Router's ** transition ** parameter using the ** TransitionType ** enum.

        module: AdminModule(),
        transition: TransitionType.fadeIn), //use for change transition

If you use transition in a module, all routes in that module will inherit this transition animation.

Router generic types #

You may need to navigate to a specific page and request a return value in the pop(), You can type the Router object with the value of that return;

  List<Router> get routers => [
    //type router with return type
    Router<String>('/event', child: (_, args) => EventPage()),

Flutter Web url Routes #

The Routing System also recognizes what is typed in the website url (flutter web) so what you type in the browser url will open in the app. We hope this makes it easier for Flutter Web sites to make SEO more unique.

Dynamic routes apply here as well:

this will open the Product view and args.params ['id']) will be equal to 1.

Dependency Injection #

You can inject any class into your module using getter 'binds', for example classes BLoC, ChangeNotifier or Stores.

Bind is responsible for configuring object injection.

class AppModule extends MainModule {

 // here will be any class you want to inject into your project (eg bloc, dependency)
  List<Bind> get binds => [
    Bind((i) => AppBloc()), // using bloc
    Bind((i) => Counter()), // using ChangeNotifier

// here will be the routes of your module
  List<Router> get routers => [
      Router("/", child: (_, args) => HomePage()),
      Router("/login", child: (_, args) => LoginPage()),

// add your main widget here
  Widget get bootstrap => AppWidget();

Let's assume that for example we want to retrieve AppBloc inside HomePage.

//code in bloc
import 'package:get_modular/get_modular.dart' show Disposable;

// you can extend or implement from Disposable to define a discard for your class, if not.

class AppBloc extends Disposable {

  StreamController controller = StreamController();

  void dispose() {

Retrieving in view using injection. #

You have some ways to retrieve your injected classes.

class HomePage extends StatelessWidget {

  Widget build(BuildContext context) {

    // You can use the object Inject to retrieve..
    final appBloc = Modular.get<AppBloc>();

By default, objects in Bind are singletons and lazy. When Bind is lazy, the object will only be instantiated when it is called for the first time. You can use 'lazy:false' if you want your object to be instantiated immediately.

Bind((i) => OtherWidgetNotLazy(), lazy: false),

If you do not want the injected object to have a single instance, just use 'singleton: false', this will cause your object to be instantiated every time it is called

Bind((i) => OtherWidgetNotLazy(), singleton: false),

Using Modular widgets to retrieve your classes #

ModularState #

class MyWidget extends StatefulWidget {
  _MyWidgetState createState() => _MyWidgetState();

class _MyWidgetState extends ModularState<MyWidget, HomeController> {

  //variable controller
  //automatic dispose off HomeController

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Modular"),
      body: Center(child: Text("${controller.counter}"),),

ModuleWidget #

The same structure as ChildModule. Very useful for modular TabBar visualizations.

class TabModule extends ModuleWidget {

  List<Bind> get binds => [
    Bind((i) => TabBloc(repository: i.get<TabRepository>())),
    Bind((i) => TabRepository()),

  Widget get view => TabPage();


Consuming a ChangeNotifier Class #

Example of a ChangeNotifier Class:

import 'package:flutter/material.dart';

class Counter extends ChangeNotifier {
  int counter = 0;

  increment() {

you can use the Consumer to manage the state of a widget block.

class HomePage extends StatelessWidget {
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text("Home"),
      body: Center(
     // recognize the ChangeNotifier class and rebuild when notifyListeners () is called
        child: Consumer<Counter>(
          builder: (context, value) {
            return Text('Counter ${value.counter}');
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          // retrieving the class directly and executing the increment method

Creating Child Modules. #

You can create other modules in your project, so instead of inheriting from MainModule, you should inherit from ChildModule.

class HomeModule extends ChildModule {
  List<Bind> get binds => [
    Bind((i) => HomeBloc()),

  List<Router> get routers => [
    Router("/", child: (_, args) => HomeWidget()),
    Router("/list", child: (_, args) => ListWidget()),

  static Inject get to => Inject<HomeModule>.of();


From this you can call your modules on the main module route.

class AppModule extends MainModule {

  List<Router> get routers => [
        Router("/home", module: HomeModule()),

Consider splitting your code into modules such as LoginModule, and into it placing routes related to that module. Maintaining and sharing code in another project will be much easier.

Lazy Loading #

Another benefit you get when working with modules is to load them "lazily". This means that your dependency injection will only be available when you navigate to a module, and as you exit that module, Modular will wipe memory by removing all injections and executing the dispose() methods (if available) on each module. injected class refers to that module.

Unit Test #

You can use the dependency injection system to replace Links from mock links,as an example of a repository. You can also do it using "Inversion of Control"

  List<Bind> get binds => [
        Bind<ILocalStorage>((i) => LocalStorageSharePreferences()),

We have to import the "get_modular_test" to use the methods that will assist with Injection in the test environment.

import 'package:get_modular/get_modular_test.dart';
import 'package:flutter_test/flutter_test.dart';

main() {
  test('change bind', () {
    initModule(AppModule(), changeBinds: [
      Bind<ILocalStorage>((i) => LocalMock()), 
    expect(Modular.get<ILocalStorage>(), isA<LocalMock>());

DebugMode #

Remove prints debug:

Modular.debugMode = false;

Roadmap #

This is currently our roadmap, please feel free to request additions/changes.

DI by Module
Routes by Module
Widget Consume for ChangeNotifier
Integration with flutter_bloc
Integration with mobx
Multiple routes
Pass arguments by route
Pass url parameters per route
Route Transition Animation

Features and bugs #

Please send feature requests and bugs at the issue tracker.

Created from templates made available by Stagehand under a BSD-style license. license.

[0.5.3] - 18 Feb 2020 #

  • improve Get support

[0.5.2] - 18 Feb 2020 #

  • added support do Get

[0.5.1] - 15 Feb 2020 #

  • fix #52

[0.5.0] - 13 Feb 2020 #

  • Added router generic type
  List<Router> get routers => [
    //type router with return type
    Router<String>('/event', child: (_, args) => EventPage()),

Now you can type your pushNamed and pop

 String value = await<String>();
 //and'My String');

[0.4.7] - 9 Feb 2020 #

  • Added Custom Transition.
  • Added Modular.args (get route params in Controller).
  • (PREVIEW) RouterGuard in child routes.
  • Fix error in WidgetTests
  • Added Print routers in debugMode

[0.4.5] - 7 Feb 2020 #

  • Added not lazy Objects
  List<Bind> get binds => [
        Bind((i) => OtherWidgetNotLazy(), lazy: false),

[0.4.4] - 6 Feb 2020 #

  • fix RouterGuards
  • Added Modular.debugMode = false;
  • Improve documentations
  • Fix Error in initalRoute

[0.4.3] - 1 Feb 2020 #

  • fix RouterGuards
  • Added Modular.debugMode = false;

[0.4.2] - 1 Feb 2020 #

  • fix routerGuards
  • fix tests

[0.4.1] - 30 Jan 2020 #

  • Internal Inject Interface reference

[0.4.0] - 28 Jan 2020 #

  • added Modular.dispose();
  • ModularState
  • Removed InjectMixin

[0.3.5+1] - 26 Jan 2020 #

  • fix module widget
  • fix inject error

[0.3.3+1] - 18 Jan 2020 #

  • Modular is BETA!!!
  • You can now control navigation without the context!
  • Added and replace Navigator.of(context)
  • Added Modular.get and replace
  • Added flag "singleton" in Bind injection
  • Fix Router Guard

[0.1.8] - 08 Jan 2020 #

  • fix test errors (initModule)
  • Added modularException

[0.1.4] - 24 Dec 2019 #

  • fix #7 and more

[0.1.3] - 17 Dec 2019 #

  • Route Settings, RemoveUntil fix #11

[0.1.1] - 17 Dec 2019 #

  • Fix tests

[0.1.0+1] - 16 Dec 2019 #

  • Added Route Transitions.
  • Change ModularWidget to ModularApp.

[0.0.10] - 14 Dec 2019 #

  • Added logo

[0.0.8] - 13 Dec 2019 #

  • Route Guard

[0.0.7] - 10 Dec 2019 #

  • Dynamic Router
  • Added Doc Translation
  • Change BrowserModule to MainModule
  • Change CommonModule to ChildModule
  • Corrigido erro de blink na primeira rota
  • fix routes param

[0.0.1] - 8 Dec 2019 #

  • First Release


import 'package:example/app/app_module.dart';
import 'package:flutter/material.dart';
import 'package:get_modular/get_modular.dart';

void main() => runApp(ModularApp(module: AppModule()));

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  get_modular: ^0.5.3

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:get_modular/get_modular.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/get_modular_test.dart.

Run flutter format to format lib/get_modular_test.dart.

Format lib/src/interfaces/route_guard.dart.

Run flutter format to format lib/src/interfaces/route_guard.dart.

Format lib/src/transitions/page_transition.dart.

Run flutter format to format lib/src/transitions/page_transition.dart.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
flutter 0.0.0
get ^1.10.1 1.11.6 1.13.1-dev
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies