Flutter状态管理插件mobx_architecture的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter状态管理插件mobx_architecture的使用

MobX架构

Hello! 这个包允许你更方便和整洁地将你的MobX存储与UI绑定。 目前,它主要关注于将ViewModel绑定到UI,并提供了MediaQueryData的实例,以便更方便地调整小部件大小、获取方向等。(没有人希望MediaQueries散落在各个地方,对吧?)

如果你喜欢这个包,请在GitHub上给它加星。任何贡献,无论是文档还是代码,无论是错误修复还是新功能或特性请求,都是极其欢迎并鼓励的。

这个包有很大的潜力,我计划定期维护这个包并添加新功能。因此,任何你觉得能提升这个包的新功能,请不要犹豫,在包的仓库中提出一个特性请求。

开始使用

首先,让我们了解一下一些介绍、假设和需求

这个包帮助实现了一个自定义版本的MVVM架构模式,将Flutter MobX文档中提到的Widget-Store-Service组织模式与传统的Model-View-ViewModel架构模式结合在一起,形成一个统一的模式,其中:

  • Model 相对不变,包含服务、API调用等。
  • ViewModel 与MobX Store统一起来,其双重作用是管理状态(本地、共享或其他)以及相应View的业务逻辑。
  • View 相对不变,主要区别在于必要时会在UI中插入Observer小部件,这些小部件根据应用程序的状态来渲染UI。

注意事项:

  • 你正在使用MVVM架构模式来构建你的应用。
  • 你正在使用Provider来注入你的MobX存储。(虽然不强制要求,但强烈建议这样做,因为包内部使用了Provider来注入存储。)

必须使用的额外包:

  • MobX(当然)
  • Flutter Mobx(用于Observer小部件,你可能已经在使用了)

注意:

  • 强烈建议与MobX和本包一起使用Provider,因为它内部使用了Provider来注入存储。
  • 如果在没有Provider作为依赖的情况下使用依赖于Provider的部分(如.usesProvider构造函数),可能会导致意外行为。

推荐使用的其他包:

  • Get_it 用于服务定位器(即使Provider已经是依赖项之一,这个包对于注入服务和从ViewModel中访问它们也很有用,尤其是在BuildContext不可用时)
  • Hive 用于本地数据持久化

包暴露的四个小部件及其变体

这个包暴露了四个小部件,每个小部件有六种不同的实现方式(通过构造函数)。这些小部件和它们的变化基于以下三个要求:

  • 绑定一个不是MobX Store的ViewModel
  • 绑定一个MobX Store的ViewModel
  • 无状态和有状态的上述标准变化,以便在需要时访问小部件生命周期方法,如initState()dispose()

这些小部件如下:

StatefulVMStoreBuilder<T>

这个小部件用于当你需要访问小部件生命周期方法并且要将一个也是MobX Store的ViewModel绑定到UI时。它有两个构造函数:

  • StatefulVMStoreBuilder<T>.usesProvider()

    StatefulVMStoreBuilder<Store>.usesProvider(
      key: ///可选键,
      builder: (BuildContext context, T store, SizingInfo sizingInfo) {
        /// 提供store、BuildContext和屏幕尺寸信息对象
        return Widget();
      },
      initState: (store) {
        /// 可选的初始化方法
      },
      dispose: (store) {
        /// 可选的清理方法
      },
    );
    
  • StatefulVMStoreBuilder<T>.standAlone()

    StatefulVMStoreBuilder<Store>.standAlone(
      key: ///可选键,
      viewModelStoreBuilder: () => MyViewModelStore(),
      builder: (BuildContext context, T store, SizingInfo sizingInfo) {
        /// 提供store、BuildContext和屏幕尺寸信息对象
        return Widget();
      },
      initState: (store) {
        /// 可选的初始化方法
      },
      dispose: (store) {
        /// 可选的清理方法
      },
    );
    

    注意: 如果使用此构造函数,则必须使用来自Flutter Mobx包的Observer小部件,不应使用setState或其他方式重新触发小部件的构建函数,因为Store是在build方法内部实例化的,重新触发会导致创建一个新的Store。

StatelessVMStoreBuilder<T>

这个小部件用于当你不需要访问小部件生命周期方法并且要将一个也是MobX Store的ViewModel绑定到UI时。它也有两个构造函数:

  • StatelessVMStoreBuilder<T>.usesProvider()

    StatelessVMStoreBuilder<Store>.usesProvider(
      key: ///可选键,
      builder: (BuildContext context, T store, SizingInfo sizingInfo) {
        /// 提供store、BuildContext和屏幕尺寸信息对象
        return Widget();
      },
    );
    
  • StatelessVMStoreBuilder<T>.standAlone()

    StatelessVMStoreBuilder<Store>.standAlone(
      key: ///可选键,
      viewModelStoreBuilder: () => MyViewModelStore(),
      builder: (BuildContext context, T store, SizingInfo sizingInfo) {
        /// 提供store、BuildContext和屏幕尺寸信息对象
        return Widget();
      },
    );
    

    注意: 如果使用此构造函数,则必须使用来自Flutter Mobx包的Observer小部件,不应使用setState或其他方式重新触发小部件的构建函数,因为Store是在build方法内部实例化的,重新触发会导致创建一个新的Store。

StatefulVMBuilder<T>

这个小部件用于当你需要访问小部件生命周期方法并且要将一个不是MobX Store的ViewModel绑定到UI时。

StatefulVMBuilder<Object>(
  key: ///可选键,
  viewModelStoreBuilder: () => MyViewModel(),
  builder: (BuildContext context, T viewModel, SizingInfo sizingInfo) {
    /// 提供ViewModel、BuildContext和屏幕尺寸信息对象
    return Widget();
  },
  initState: (viewModel) {
    /// 可选的初始化方法
  },
  dispose: (viewModel) {
    /// 可选的清理方法
  },
);

StatelessVMBuilder<T>

这个小部件用于当你不需要访问小部件生命周期方法并且要将一个不是MobX Store的ViewModel绑定到UI时。

StatelessVMBuilder<Object>(
  key: ///可选键,
  viewModelStoreBuilder: () => MyViewModel(),
  builder: (BuildContext context, T viewModel, SizingInfo sizingInfo) {
    /// 提供ViewModel、BuildContext和屏幕尺寸信息对象
    return Widget();
  },
);

许可证

该包遵循Apache许可证,版本2.0。

Copyright 2021 Tanzil Zubair Bin Zaman

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

完整示例

下面是完整的示例代码,展示了如何使用mobx_architecture包来管理状态。

示例代码

Counter Example 使用Provider和无状态小部件

class CounterExample1 extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatelessVMStoreBuilder<CounterStore>.usesProvider(
          builder: (context, counterStoreVM, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterStoreVM.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterStoreVM.increment();
                      })
                ],
              ),
            );
          },
        ),
      );
}

Counter Example 不使用Provider和无状态小部件

class CounterExample2 extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatelessVMStoreBuilder<CounterStore>.standAlone(
          viewModelStoreBuilder: () => CounterStore(),
          builder: (context, counterStoreVM, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterStoreVM.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterStoreVM.increment();
                      })
                ],
              ),
            );
          },
        ),
      );
}

Counter Example 使用Provider和有状态小部件

class CounterExample3 extends StatefulWidget {
  [@override](/user/override)
  _CounterExample3State createState() => _CounterExample3State();
}

class _CounterExample3State extends State<CounterExample3> {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatefulVMStoreBuilder<CounterStore>.usesProvider(
          builder: (context, counterStoreVM, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterStoreVM.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterStoreVM.increment();
                      })
                ],
              ),
            );
          },
          initState: (counterModel) {
            counterModel.init();
          },
          dispose: (counterModel) {
            counterModel.dispose();
          },
        ),
      );
}

Counter Example 不使用Provider和有状态小部件

class CounterExample4 extends StatefulWidget {
  [@override](/user/override)
  _CounterExample4State createState() => _CounterExample4State();
}

class _CounterExample4State extends State<CounterExample4> {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatefulVMStoreBuilder<CounterStore>.standAlone(
          viewModelStoreBuilder: () => CounterStore(),
          builder: (context, counterStoreVM, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterStoreVM.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterStoreVM.increment();
                      })
                ],
              ),
            );
          },
          initState: (counterModel) {
            counterModel.init();
          },
          dispose: (counterModel) {
            counterModel.dispose();
          },
        ),
      );
}

Counter Example 不使用MobX和有状态小部件

class CounterExample5 extends StatefulWidget {
  [@override](/user/override)
  _CounterExample5State createState() => _CounterExample5State();
}

class _CounterExample5State extends State<CounterExample5> {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatefulVMBuilder<CounterVModel>(
          viewModelBuilder: () => CounterVModel(value: 0),
          builder: (context, counterModel, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterModel.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterModel.increment();
                      })
                ],
              ),
            );
          },
          initState: (counterModel) {
            counterModel.init();
          },
          dispose: (counterModel) {
            counterModel.dispose();
          },
        ),
      );
}

Counter Example 不使用MobX和无状态小部件

class CounterExample6 extends StatefulWidget {
  [@override](/user/override)
  _CounterExample6State createState() => _CounterExample6State();
}

class _CounterExample6State extends State<CounterExample6> {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('MobX Counter'),
        ),
        body: StatelessVMBuilder<CounterVModel>(
          viewModelBuilder: () => CounterVModel(value: 0),
          builder: (context, counterModel, sizingInfo) {
            return Container(
              height: sizingInfo.size.height,
              width: sizingInfo.size.width,
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Observer(
                    builder: (_) => Text(
                      '${counterModel.value}',
                      style: const TextStyle(fontSize: 20),
                    ),
                  ),
                  IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () {
                        counterModel.increment();
                      })
                ],
              ),
            );
          },
        ),
      );
}

更多关于Flutter状态管理插件mobx_architecture的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件mobx_architecture的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用mobx_architecture插件进行状态管理的代码示例。mobx_architecture是一个结合了MobX和Flutter的架构插件,它能够帮助你有效地管理应用状态。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加mobx_architecture及其依赖项:

dependencies:
  flutter:
    sdk: flutter
  mobx_dart: ^2.0.0  # MobX Dart库
  mobx_flutter: ^2.0.0  # MobX Flutter绑定
  mobx_architecture: ^0.x.x  # 假设这是最新的版本,请检查pub.dev获取实际版本

2. 创建Store

接下来,创建一个用于管理应用状态的Store。例如,我们创建一个简单的计数器Store:

// counter_store.dart

import 'package:mobx_dart/mobx_dart.dart';

class CounterStore = _CounterStore with _$CounterStore;

abstract class _CounterStore with Store {
  @observable
  int count = 0;

  @action
  void increment() {
    count++;
  }

  @action
  void decrement() {
    count--;
  }
}

3. 提供Store

使用Provider将Store提供给应用中的组件。mobx_architecture通常与flutter_mobx一起使用来绑定UI和状态:

// main.dart

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx_architecture/mobx_architecture.dart';
import 'counter_store.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MobxProvider(
      store: CounterStore(),
      child: MaterialApp(
        home: CounterScreen(),
      ),
    );
  }
}

4. 使用Store

在UI组件中使用Observer来监听Store的变化,并绑定到UI元素:

// counter_screen.dart

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'counter_store.dart';

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final store = MobxProvider.of<CounterStore>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Observer(
              builder: (_) => Text(
                '${store.count}',
                style: Theme.of(context).textTheme.headline4,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => store.increment(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

5. 运行应用

现在你可以运行你的Flutter应用,你应该能看到一个计数器应用,当你点击浮动按钮时,计数会增加。

总结

这个示例展示了如何在Flutter中使用mobx_architecture插件进行状态管理。通过创建Store、提供Store并在UI组件中使用Observer来监听和更新状态,你可以有效地管理应用的复杂状态。确保你根据项目的具体需求调整Store和UI逻辑。

回到顶部