Flutter插件fountain的介绍与使用_fountain是一个用于 Flutter 的模块化状态管理解决方案

发布于 1周前 作者 yuanlaile 最后一次编辑是 5天前 来自 Flutter

Flutter插件fountain的介绍与使用_fountain是一个用于 Flutter 的模块化状态管理解决方案

插件fountain介绍

fountain 是一个用于 Flutter 的模块化状态管理解决方案。它具有以下特点:

  • 易于调试:每个事件都是可预测的,并进入单一流水线。
  • 集中式状态:具有强大的状态验证机制。
  • 异步生成器的强大功能:借助 Dart 生成器,编写异步代码变得非常简单。

快速开始

全局逻辑状态

首先定义应用的全局逻辑状态:

class CounterState {
  factory CounterState.initial() => const CounterState(0, 10);
  const CounterState(this.count, this.max);
  final int count;
  final int max;
  bool get isMax => count >= max;
}

可用的操作

定义可以改变应用逻辑状态的操作:

class AddAction extends Action<CounterState> {
  const AddAction(this.value);
  final int value;
  @override
  Stream<Updater<CounterState>> call(
    Context<CounterState> context,
  ) async* {
    yield (state) => CounterState(min(state.count + value, state.max), state.max);
  }
}

class ResetAction extends Action<CounterState> {
  @override
  Stream<Updater<CounterState>> call(
    Context<CounterState> context,
  ) async* {
    yield (state) => CounterState(0, state.max);
  }
}

class SaveAction extends Action<CounterState> {
  @override
  Stream<Updater<CounterState>> call(
    Context<CounterState> context,
  ) async* {
    await File(_cachePath).writeAsString(context.state.count.toString());
  }
}

class LoadAction extends Action<CounterState> {
  @override
  Stream<Updater<CounterState>> call(
    Context<CounterState> context,
  ) async* {
    final content = await File(_cachePath).readAsString();
    final count = int.parse(content);
    yield (state) => CounterState(min(count, state.max), state.max);
  }
}

视图订阅状态变化并分发操作

创建一个视图来订阅状态变化并分发操作:

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Builder(
              builder: (context) {
                /// 这个小部件将在每次 `count` 值更改时重建
                final count = context.select((CounterState state) => state.count);
                return Text(
                  '$count',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: Builder(
        builder: (context) {
          /// 这个小部件将在每次 `isMax` 值更改时重建
          final isMax = context.select((CounterState state) => state.isMax);
          if (isMax) {
            return FloatingActionButton(
              /// 操作在 [ApplicationContext] 中执行
              onPressed: () => context.dispatch<CounterState>(ResetAction()),
              tooltip: 'Reset',
              child: Icon(Icons.delete),
            );
          }

          return FloatingActionButton(
            /// 操作在 [ApplicationContext] 中执行
            onPressed: () => context.dispatch<CounterState>(AddAction(1)),
            tooltip: 'Increment',
            child: Icon(Icons.add),
          );
        },
      ),
    );
  }
}

状态初始化

在树的根部使用 Fountain 小部件初始化状态:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Fountain(
      initialState: (context) => CounterState.initial(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(),
      ),
    );
  }
}

核心概念

上下文(Context)

应用程序上下文维护应用程序的唯一全局逻辑不可变状态。

上下文还包含所有将处理分发事件的中间件。

应用程序上下文由 Fountain 提供给小部件树,以便任何后代小部件都可以使用 select 扩展方法观察状态的属性。它还可以通过 dispatch 扩展方法向中间件分发事件。

中间件(Middleware)

应用程序中间件处理分发的事件并可能产生状态更新。

它们本质上是可组合的,这意味着每个中间件可以包装另一个中间件。

事件(Event)

事件是中间件的输入。它们可以描述用户操作或系统事件等。它们由中间件处理,可以产生新的应用程序状态。

包含的中间件

要导入中间件,使用 import 'package:fountain/middlewares.dart'; 指令。

动作(Actions)

默认情况下,框架包括一个 ActionExecutor<TState> 中间件,允许定义 Action<TState>,然后直接调用以生成新状态。

定义一个动作

为了创建自定义动作,继承自 Action<TState> 并在 call 方法中实现所有更新逻辑。由于该方法返回 Stream,通常使用 async * 生成器实现逻辑,这允许 yield 一系列状态更新。

class RefreshAction extends Action<MyApp> {
  const RefreshAction();

  @override
  Stream<Updater<CounterState>> call(
    Context<CounterState> context,
  ) async* {
    if (!context.state.isLoading) {
        yield (state) => state.copyWith(
            isLoading: true,
        );

        final news = await Api.instance.getNews();

        yield (state) => state.copyWith(
            isLoading: false,
            news: news,
        );
    }
  }
}

注意,动作不会直接生成状态,而是生成 Updater。这是为了强调初始状态可能在动作执行期间发生变化,因此在更新时必须考虑这一点。

日志记录(Logging)

框架还包括一个 Logging 中间件,记录所有事件和状态更新。

Fountain(
    middlewares: <Middleware<CounterState>>[
        Logging<CounterState>(),
        ...Fountain.defaultMiddlewares<CounterState>(),
    ],
    // ...
);

错误处理器(ErrorHandler)

这个中间件捕获其下方所有未处理的异常,并在必要时分发新事件。

Fountain(
    middlewares: <Middleware<CounterState>>[
        ErrorHandler<CounterState>(
            (context, event, initialState, error, stackTrace) {
                // 在事件处理过程中发生了未知错误
                return DisplayAlertAction('Sorry, an error occurred');
            },
        ),
        ...Fountain.defaultMiddlewares<CounterState>(),
    ],
    // ...
);

更多关于Flutter插件fountain的介绍与使用_fountain是一个用于 Flutter 的模块化状态管理解决方案的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!