MoLc - Flutter state management component

MoLc is my own state management library based on Provider encapsulation. It is currently used for a small business project with 2w daily activities. The performance is not bad. I will share it with you.
MoLc is a combination of Model and Logic, designed to separate data model and business logic. I came from Android, and the MVP model was quite popular back then, so when I first came into contact with Flutter, I made such a package, which is the first version of MoLc. Let’s talk about what MoLc has achieved. Personally, I think MoLc is suitable for most medium and large-scale projects. Welcome to come to guide the shortcomings.

Learn about Modeland before using MoLc Logic.

Model

ModelIt is the class that stores the Widget state, which can be used directly

class TestModel extends Model {}
复制代码

If you want to Modeluse it in context, for example, you need to contextget the text through S.of(context), then use a subclassWidgetModel

class Test1Model extends WidgetModel {}
复制代码

contextGet the upper layer contextin Modelthe sub context.read<T>(), which is provided by the Provider, and everyone should be familiar with it.

  • refresh
test1Model.refresh();
复制代码
  • Selector

Different from Provider 's Selector, MoLc's Selector is used for refined refresh.

MixingSelectorMixin<T>

class TestModel extends Model with SelectorMixin<Tuple3>{}
复制代码

Implement the T selectWith();method , whether the return value changes or not determines whether the Model is refreshed.

@override
Tuple3<int, String, bool> selectWith() {
  return Tuple3(this.field1, this.field2, this.field3);
}
复制代码

Logic

Logicis a class that stores business logic, using

class TestLogic extends Logic {}
复制代码

同样可以在子context中获取上层context的Logic,也是用context.read<T>()Logic也提供了子类WidgetLogic用于获取context
另外,Logic还提供了MoLogic提供Model,但不建议在普通业务逻辑函数中使用,不然数据模型和业务逻辑分离的初衷就被破坏了。仅建议在dispose中使用model,用来执行一些页面或者小组件销毁时需要的逻辑。

MoLcWidget

MoLc的核心组件是 ModelWidgetLogicWidgetMoLcWidget,前两个适合只有Model或者Logic的Widget,用的比较少,重点讲一下MoLcWidget,下面是MoLcWidget的写法:

class ExamplePage extends StatelessWidget {
  const ExamplePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MoLcWidget<_ExampleModel, _ExampleLogic>(
      modelCreate: (_) => _ExampleModel(),
      logicCreate: (_) => _ExampleLogic(),
      init: (_, model, logic) => logic.init(model),
      builder: (context, model, logic, __) => Container(),
    );
  }
}

class _ExampleModel extends Model {}

class _ExampleLogic extends Logic {
  void init(_ExampleModel model) {}
}
复制代码

如同Provider一样,还是有些样板代码,不过可以使用IDE的Live Template,也还算方便。MoLc把model和logic从Widget里分离出去,你可以在model里定义Widget的状态,可以在logic写Widget逻辑代码,然后在MoLcWidget里面调用。看到这里你可能觉得没什么,只是对Provider的一层封装而已,没错,这就是他的第一个版本的基本功能。

TopProvider

接下来说数据共享,很多使用Provider的人可能用的最多的反而是处于APP之上的顶级Model,像这样:

MultiProvider(
      providers: ...,     
      child: MaterialApp(
        ...
      ),
    ),
复制代码

这是由于InheritedWidget的特性,context节点位置要位于MaterialApp 之上才能让App中的所有路由页面访问到,才能实现跨页面传输数据。这里MoLc封装了一层TopProvider,用于内部的一些全局容器的实现和更方便的访问TopModel

TopProvider(
  providers: ...,
  child: MaterialApp(
    ...
  ),
),
复制代码

TopModel

  • 全局获取

在MoLc中,顶级Mode被命名为TopModel,继承于Model,在上述TopProvider里注册。你几乎可以在任意地方通过顶级函数top<T>()来获取你需要的TopModel,而不需要传入context

  • 局部刷新

在实际项目中顶级Model带来了另一个问题,顶级Model的刷新会导致整个App的build,也就是性能问题。为了解决这个问题,MoLc定义了一个名为EventModel<T>Mixin,T为Event的类型。

你可以给为你的TopModel定义一个enum的Event:

enum TestEvent { event1, event2, event3 }
复制代码

然后TopModel混入EventModel<T>

class TestTopModel extends TopModel with EventModel<TestEvent> {}
复制代码

需要监听的Model混入EventConsumerMixin

class Test2Model extends Model with EventConsumerForModel {}
复制代码

Model监听Event

model.listenTopModelEvent(TestEvent.event4);
复制代码

TopModel发送Event

testTopModel.refreshEvent(TestEvent.event4)
复制代码

这样就完成的TopModel对于需要监听部分事件Model的局部刷新。

ExposedMixin

上面提到过InheritedWidget的特性,只能实现子context对于父context的数据访问。而实际在业务中,我们常常会遇到父context访问子context的需求,或者需要兄弟context相互访问。MoLc也提供了这样的实现,只需要混入一个ExposedMixin

Model混入ExposedMixin

class Test3Model extends Model with ExposedMixin {}
复制代码

然后你就可以在任意地方通过顶级函数find<T>()获取到这个Model,如果这个Model当前不存在或者已经disposed是获取不到的。

Logic混入ExposedMixin

class Test3Logic extends Logic with ExposedMixin {}
复制代码

此时的Logic你可以在任意地方进行调用,轻松的实现了Logic的复用。这里有一个TODO:未注册在BuildContext中的Logic的调用,目前只能调用当前APP的BuildContext树中存在的Logic

最后放上pub链接,感兴趣可以尝试一下。

Guess you like

Origin juejin.im/post/7082604401801560095