Flutter层次状态管理插件hierarchical_state_machine的使用

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

Flutter层次状态管理插件hierarchical_state_machine的使用

Hierarchical State Machine (HSM) 插件是一个类似于UML状态图的状态机实现,用Dart编写。它允许将状态组织成父子关系,使更通用的包含状态能够执行常见的事件处理。此外,这个状态机还支持并行或“正交区域”。

重要概念

最重要的信息可以在EventHandler类中找到:

/// Order of operations for the following state, assuming event T1 is fired and
/// s11 is the current state.
///     1) T1 delivered to s1
///     2) Guard g() is called. If it returns false, stop.
///     3) a(), b(), t(), c(), d(), e()
/// ┌──────────────────────────|s|──────────────────────────┐
/// │┌────|s1|────┐                    ┌────|s2|───────────┐│
/// ││exit:b()    │                    │entry:c()          ││
/// ││┌──|s11|──┐ │                    │-*:d()->┌──|s21|──┐││
/// │││exit:a() │ │--T1{guard:g(),     │        │entry:e()│││
/// │││         │ │      action:t()}-->│        │         │││
/// ││└─────────┘ │                    │        └─────────┘││
/// │└────────────┘                    └───────────────────┘│
/// └───────────────────────────────────────────────────────┘

Fork / Join伪状态

并发状态已经以ParallelState的形式存在。虽然语义不够完美,但你可以在自己的机器中实现这一点。

历史和深层历史

初始状态是可变的,并在目标状态的onEnter之后进行评估。虽然不是完美的语义,但在你自己的机器中非常实用。

条件判断

事件处理器有守卫(guards),这些可以用来决定给定事件转换到的目标。

事件延迟

简单的延迟可以通过捕获事件并在退出时重播它们来本地完成。虽然不是完美的,但它确实让未来状态定义自己的延迟列表来重新捕获事件。

示例代码

以下是一个完整的示例demo,展示了如何使用hierarchical_state_machine插件:

import 'package:hierarchical_state_machine/hierarchical_state_machine.dart';

void main() {
  final machine = HierarchicalStateMachine(
    initialState: State('s1', [
      State('s11', [], onEnter: () => print('Entering s11')),
    ]),
    onEvent: (event, currentState) {
      print('Event $event received in state $currentState');
    },
  );

  // Define transitions
  machine.addTransition('T1', 's11', 's21', guard: () => true, action: () => print('Transitioning from s11 to s21'));

  // Simulate an event
  machine.fire('T1');
}

class State {
  final String name;
  final List<State> children;
  final VoidCallback? onEnter;

  State(this.name, this.children, {this.onEnter});

  @override
  String toString() => name;
}

在这个示例中,我们创建了一个简单层次状态机,定义了两个状态s1s11,并添加了一个从s11s21的转换。当触发事件T1时,状态机会根据定义的转换规则进行状态切换,并打印相应的日志信息。

通过这种方式,你可以轻松地构建复杂的应用逻辑,利用层次状态机的强大功能来管理和响应各种应用状态的变化。


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

1 回复

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


当然,下面是一个关于如何在Flutter中使用hierarchical_state_machine插件进行层次状态管理的代码案例。这个插件允许你创建具有层次结构的状态机,非常适合管理复杂的UI状态。

首先,确保你已经在你的pubspec.yaml文件中添加了hierarchical_state_machine依赖:

dependencies:
  flutter:
    sdk: flutter
  hierarchical_state_machine: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们来看一个具体的代码示例。

1. 定义状态与事件

首先,定义你的状态和事件。假设我们有一个简单的音乐播放器应用,它有播放、暂停和停止三个状态,以及播放、暂停和停止三个事件。

import 'package:hierarchical_state_machine/hierarchical_state_machine.dart';

// 定义状态
enum PlayerState { playing, paused, stopped }

// 定义事件
enum PlayerEvent { play, pause, stop }

2. 创建状态机配置

接下来,我们需要配置状态机,包括状态的转换规则。

class PlayerStateMachineConfig extends HierarchicalStateMachineConfig<PlayerState, PlayerEvent> {
  @override
  List<Transition<PlayerState, PlayerEvent>> get transitions => [
    Transition<PlayerState, PlayerEvent>(
      from: PlayerState.stopped,
      event: PlayerEvent.play,
      to: PlayerState.playing,
    ),
    Transition<PlayerState, PlayerEvent>(
      from: PlayerState.playing,
      event: PlayerEvent.pause,
      to: PlayerState.paused,
    ),
    Transition<PlayerState, PlayerEvent>(
      from: PlayerState.paused,
      event: PlayerEvent.play,
      to: PlayerState.playing,
    ),
    Transition<PlayerState, PlayerEvent>(
      from: [PlayerState.playing, PlayerState.paused],
      event: PlayerEvent.stop,
      to: PlayerState.stopped,
    ),
  ];

  @override
  PlayerState get initialState => PlayerState.stopped;
}

3. 创建并使用状态机

现在,我们可以创建状态机实例,并监听状态变化。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Hierarchical State Machine Demo')),
        body: StateMachineWidget(),
      ),
    );
  }
}

class StateMachineWidget extends StatefulWidget {
  @override
  _StateMachineWidgetState createState() => _StateMachineWidgetState();
}

class _StateMachineWidgetState extends State<StateMachineWidget> {
  late HierarchicalStateMachine<PlayerState, PlayerEvent> _stateMachine;

  @override
  void initState() {
    super.initState();
    final config = PlayerStateMachineConfig();
    _stateMachine = HierarchicalStateMachine<PlayerState, PlayerEvent>(config);
    _stateMachine.addListener(() {
      setState(() {});
    });
  }

  void _handleEvent(PlayerEvent event) {
    _stateMachine.transitionTo(event);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('Current State: ${describeEnum(_stateMachine.currentState)}'),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: () => _handleEvent(PlayerEvent.play),
          child: Text('Play'),
        ),
        ElevatedButton(
          onPressed: () => _handleEvent(PlayerEvent.pause),
          child: Text('Pause'),
        ),
        ElevatedButton(
          onPressed: () => _handleEvent(PlayerEvent.stop),
          child: Text('Stop'),
        ),
      ],
    );
  }
}

解释

  1. 定义状态和事件PlayerStatePlayerEvent分别定义了播放器的状态和事件。
  2. 创建状态机配置PlayerStateMachineConfig类定义了状态转换规则。
  3. 创建并使用状态机:在StateMachineWidget中,我们创建了一个状态机实例,并添加了监听器来更新UI。通过_handleEvent方法,我们可以触发状态转换。

这个示例展示了如何使用hierarchical_state_machine插件来管理一个简单的音乐播放器的状态。你可以根据需要扩展状态和事件,以适应更复杂的场景。

回到顶部