momentum 2.2.1 copy "momentum: ^2.2.1" to clipboard
momentum: ^2.2.1 copied to clipboard

MVC pattern for flutter. Works as state management, dependency injection and service locator.

#

MVC pattern for flutter. Works as state management, dependency injection and service locator.

Pub Version Test GitHub stars GitHub license GitHub last commit


Model View Controller

Here's a diagram describing the flow between the (model), (view) and the (controller):

Both MomentumController and MomentumModel are abstract classes that needs to be implemented. A pair of model and controller is called a component. MomentumBuilder is simply a widget. This is used to listen to controllers for rebuilds and accessing models to display their values.

Example #

If you want to see a full code example that runs. Visit the example tab for more details or you can visit the official webpage. Otherwise, if you only want to see a glimpse of how momentum works, read the Overview and FAQs below.

Advance Example: Listify (clone the repo and run the app, requires Flutter 2.0.0)

Overview #

MomentumModel - the data or state. Must be Immutable.

class ProfileModel extends MomentumModel<ProfileController> {
  // ...

  final int userId;
  final String username;

  // ...
}
copied to clipboard

MomentumBuilder - the view or widget to display the state.

MomentumBuilder(
  controllers: [ProfileController], /// injects both `ProfileController` and `ProfileModel`.
  builder: (context, snapshot) {
    var profileState = snapshot<ProfileModel>(); /// grab the `ProfileModel` using snapshot.
    var username = profileState.username;
    return // some widgets here ...
  }
)
copied to clipboard

MomentumController - the logic to manipulate the model or state.

class ProfileController extends MomentumController<ProfileModel> {
  // ...

  Future<void> loadProfile() async {
    var profile = await http.get(...);
    // update the model's properties.
    model.update(
      userId: profile.userId,
      username: profile.username,
    );
  }

  // ...
}
copied to clipboard

FAQs #

How to rebuild the widget? #

Calling model.update(...) from inside the controller rebuilds all the MomentumBuilders that are listening to it.


How to access the model object? #

It is automatically provided by MomentumController for you to use. Inside a controller class, you can access it directly. It's never null.


How to initialize the model or state? #

By implementing the T init() method which is required by MomentumController. Like this:

class ShopController extends MomentumController<ShopModel> {

  @override
  ShopModel init() {
    return ShopModel(
      this, // required
      shopList: [],
      productList: [],
    );
  }
}
copied to clipboard

Can I access the model properties inside my controller? #

Of course. The model object is already provided by MomentumController meaning you can also directly access its properties like this:

class ShopController extends MomentumController<ShopModel> {

  bool hasProducts() {
    return model.productList.isNotEmpty;
  }
}
copied to clipboard

Is there a special setup required for Momentum to run? #

Yes, definitely. This is the required setup for Momentum in a flutter app:

void main() {
  runApp(momentum());
}

Momentum momentum() {
  return Momentum(
    child: MyApp(),
    controllers: [
      ProfileController(),
      ShopController(),
    ],
    // and more optional parameters here.
  );
}
copied to clipboard

Testing #

Momentum is highly testable. This is how a basic widget testing for momentum would look like:

void main() {

  testWidgets('should display username', (tester) async {
    var profileCtrl = ProfileController();

    await tester.pumpWidget(
      Momentum(
        child: MyApp(),
        controllers: [profileCtrl],
      ),
    );
    await tester.pumpAndSettle();

    profileCtrl.updateUsername("johndoe");
    await tester.pumpAndSettle(); // ensure rebuilds

    expect(profileCtrl.model.username, "johndoe"); // unit check
    expect(find.text("johndoe"), findsOneWidget); // widget check
  });
}
copied to clipboard

Or you might not be a fan of widget testing and only want to test your components:

void main() {

  test('should display username', () async {
    var profileCtrl = ProfileController();

    var tester = MomentumTester(
      Momentum(
        controllers: [profileCtrl],
      ),
    );
    await tester.init();

    profileCtrl.updateUsername("johndoe");
    expect(profileCtrl.model.username, "johndoe"); // unit check
  });
}
copied to clipboard

Other optional features #

  • Routing - Navigation system that supports persistence. The app will open the page where the user left off.
  • Event System - For showing dialogs, prompts, navigation, alerts.
  • Persistence State - Restore state when the app opens again.
  • Testing - Tests your widgets and logic. Built-in helper class for unit testing.

Momentum leverages the power of setState(..) and StatefulWidget behind the scenes. The feature Event System uses Stream.

Router issues #

  • The router doesn't support named routes yet.
  • The parameter handling for router is slightly verbose. And might be complicated for some. But it works magically.
  • Needs to explicitly implement RouterPage widget in order to handle the system's back button.
  • (FIXED ✅) The router breaks after hot reload. Only a problem during development but it should work in normal execution.

API Reference #

Visit the official webpage of momentum to browse the full api reference, guides, and examples.


Thanks for checking out momentum. I hope you try it soon and don't hesitate to file on issue on github. I always check them everyday.

97
likes
140
points
195
downloads

Publisher

verified publisherxamantra.dev

Weekly Downloads

2024.09.14 - 2025.03.29

MVC pattern for flutter. Works as state management, dependency injection and service locator.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

collection, flutter

More

Packages that depend on momentum