Search packages, repositories and app categories

GitHub repositoryxamantra/momentum

momentum

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

momentum project cover
Stars
119
Forks
17
Last push (UTC)
Oct 15, 2021
Project status
Active

Original README

English project snapshot. Visit GitHub for the latest content.

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 state (model), widget (view) and the logic (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;

  // ...
}

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 ...
  }
)

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,
    );
  }

  // ...
}

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: [],
    );
  }
}

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;
  }
}

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.
  );
}

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
  });
}

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
  });
}

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.

xamantra GitHub avatar
GitHub author

xamantra ↗

flutter dev

xamantraPhilippinesOfficial website ↗
LanguagesDart

Categories

Packages published by this repository

Dependencies used

Dependency list 6 items

How do I choose a repository?

Start with your use case, compare repository activity, and check the original project before adopting it.

  1. Search by repository name, owner or description, then narrow the results by topic.
  2. Compare stars, forks and recent pushes. Stars show community interest, not a guarantee of quality.
  3. Read the README, license and issues on GitHub before using a project.

Sources and maintenance

“A repository is the most basic element of GitHub.”

GitHub Docs — About repositories ↗