mvcprovider

Create a simple MVC architecture based on the Provider package. The most recommended state management package by Flutter founders.

  • Start creating value fast with a clear and well structured code.

    • Module
      • Model
      • View
      • Controller
  • Simplest lifecycle management from the controller.

    • onInit() // Called once before first view rendering
    • onReady() // Called once after first view rendering
    • onRefresh() // Called every view rendering
  • The easiest way to inject dependencies, services or providers.

   // In the module
   // You can inject all providers that you will use in children:
   final List<SingleChildWidget> providers = [
     ChangeNotifierProvider(create: (context) => MyProviderClass1()),
     ChangeNotifierProvider(create: (context) => MyProviderClass2()),
   ];
   // Then just declare those you want to use in your model, view or controller:
   final Map<Type, dynamic> dependencies = {
     MyProviderClass2: (context) => Provider.of<MyProviderClass2>(context),
   };
  • Access to your previously declared dependencies just by calling $MyProviderClass2 anywhere in your model, view or controller

Getting Started with the official Flutter example

Everybody need to create a counter module, and of course you need it too.

STEP 1

First, define your very complex model :

    class MyCounterModel extends Model {

      int _count = 0;
      set count(int value) {
         _count = value;
        notifyListeners(); // This will refresh the view
       }
      int get count => _count;
    }

STEP 2

Then define a controller that will increment the count property with a lot of mathematics operations :

    class MyCounterCtrl extends Controller<MyCounterModel> {
    
      void increment() {
        model.count++;
      }
    }

For now, you have an amazing method increment that will increment (no ?! really ??) you're model's property count which will call refresh (a method alias for the method notifyListeners inherited from her mother class ChangeNotifier) in order to refresh the view.

STEP 3

But to refresh the view. You need a view. Here it is :

    class MyCounterView extends View<MyCounterModel, MyCounterCtrl> {
    
      @override
      Widget build(BuildContext context, [Widget child]) {
        super.build(context);
    
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("Counter : ${model.count}"),
            RaisedButton(
                child: Text("Increment"),
                onPressed: ctrl.increment,
            )
          ]
        );
      }
    }

It's a bit complicated view. I'll explain : it's a text on top of a button.

Like you can see the text display our model's property count and the button execute our controller's method increment when pressed.

STEP 4

In order to make the magic happen you'll need to link these three entities together, I decided that this fusion will be called a Module but you can call this Roberto or anything else if you prefer.

Here is our module :

    class MyCounterModule extends Module<MyCounterModel, MyCounterView, MyCounterCtrl> {
    
      final MyCounterModel model = MyCounterModel();
      final MyCounterView view = MyCounterView();
      final MyCounterCtrl ctrl = MyCounterCtrl();
    }

STEP 5

At this point if you're a good developer you should have a folder named mycounter with 4 files inside :

  • The module my.counter.dart

  • The model my.counter.model.dart

  • The view my.counter.view.dart

  • The controller my.counter.ctrl.dart

To test you newly counter feature in your app just call your widget MyCounterModule() Example in your main.dart :

    void main() => runApp(AmazingSample());
    
    class AmazingSample extends StatelessWidget {
      // This widget is the root of this amazing package sample.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'MVC Provider counter demo',
          home: MyCounterModule(),
        );
      }
    }

Libraries

mvcprovider