Flutter功能扩展插件yafsm的使用

Flutter功能扩展插件yafsm的使用

Yet another finite state machine for Dart。

插件yafsm功能

  • 轻松快速地定义状态和转换。
  • 可选地为某些状态要求数据。
  • 通过在状态内嵌套机器来管理复杂性。
  • 精美地处理在机器开始之前尝试的转换。
  • 通过late关键字启用类式定义风格。
  • 零依赖 - 它只是一个Dart文件。

Flutter功能扩展插件yafsm的使用

插件yafsm安装

在您的Dart或Flutter项目中添加该包:

dart pub add yafsm

插件yafsm基本用法

设置一个状态机有三个步骤:

// 1. 声明机器、状态和转换。
final m = Machine('switch');
final isOn = m.state('on');
final isOff = m.state('off');
final turnOn = m.transition('turn on', {isOff}, isOn);
final turnOff = m.transition('turn off', {isOn}, isOff);

// 2. 设置初始状态。
m.initialize(isOff);

// 3. 启动机器。
m.start();

// 调用状态和转换来操作机器。
if (isOff()) {
  turnOn();
}

进阶用法

状态变化

您可以以两种方式响应机器状态的变化:

  1. 监听机器状态流,可通过current$访问:
m.current$.forEach((state) {
  print('现在处于状态: $state');
});
  1. 监听特定的机器状态,可通过enter$exit$访问:
isOn.enter$.forEach((_) {
  print('打开');
});

isOn.exit$.forEach((_) {
  print('关闭');
});

推荐使用enter$exit$将机器与您的应用集成。此外,状态流是唯一一种以类型安全的方式接收参数化状态数据的方法。

然而,current$流可能对调试或更高级的行为有用。

参数化状态

有时,状态需要数据。您可以使用pstate创建参数化状态,并使用ptransition创建到参数化状态的转换。

我喜欢在这里使用新的Dart记录语法。

final isOn = m.pstate<({String reason})>('on');
final turnOn = m.ptransition('turn on', {isOff}, isOn);
// ...
turnOn((reason: '害怕黑暗'));

方法名不同是为了提供每种状态类型的略微不同的接口。

守卫

状态和转换可以使用任意测试函数进行保护。

turnOn.guard(() => hasElectricity);
turnOn();
print(isOn()); // -> false

参数化守卫也可以访问提议的状态数据。

队列

从机器启动到您的代码想要开始调用转换之间可能会有一些时间。为了适应这一点,可以配置机器以队列形式存储传入的事件。

例如,以下代码按预期工作:

final m = Machine('switch', queue: true);
final isOn = m.state('on');
final isOff = m.state('off');
final turnOn = m.transition('turn on', {isOff}, isOn);

// 尝试转换 - 但我们还没有开始!
turnOn();
m.initialize(isOff);
m.start();
print(isOn()); // -> true

我发现这种队列功能有助于更自然地推理机器行为。

嵌套机器

状态往往会变得复杂;嵌套机器可以帮助解决这个问题。

要创建一个嵌套机器,可以在目标状态上调用nest。所有嵌套机器都会在原始状态被进入和退出时自动启动和停止。只需记得初始化任何嵌套机器!

final m2 = isOn.nest('on');
final isBlue = m2.state('blue light');
final isRed = m2.state('red light');
final makeRed = m2.transition('make red', {isBlue}, isRed);
m2.initialize(isBlue);
// ...
m.start();
print(isBlue(), isRed()); // -> false, false
turnOn();
print(isBlue(), isRed()); // -> true, false
makeRed();
print(isBlue(), isRed()); // -> false, true
turnOff();
print(isBlue(), isRed()); // -> false, false

嵌套机器也可以单独配置是否启用队列。

类式定义

机器定义很好地与late关键字结合使用。这使得Dart具有有趣的类式风格。以下是同一开关示例以类式风格编写:

class SwitchMachine extends Machine {
  SwitchMachine() : super('Switch') {
    initialize(isOff);
  }

  late final isOn = state('on');
  late final isOff = state('off');
  late final turnOn = transition('turn on', {isOff}, isOn);
  late final turnOff = transition('turn off', {isOn}, isOff);
}

void main() {
  final m = SwitchMachine();
  m.start();
  print(m.isOn()); // -> false
  m.turnOn();
  print(m.isOn()); // -> true
  m.turnOff();
  print(m.isOn()); // -> false
}

更多关于Flutter功能扩展插件yafsm的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter功能扩展插件yafsm的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,插件通常用于扩展应用的功能,而基于名称“yafsm”(可能代表某种有限状态机,例如“Yet Another Finite State Machine”),我们可以推测这个插件可能与状态管理有关。尽管没有具体的官方文档或定义,我们可以假设这个插件旨在帮助开发者更轻松地管理应用的状态。

以下是一个假设性的代码案例,展示了如何在Flutter中使用一个类似yafsm的插件(这里我们不会使用真实的yafsm插件,因为实际上它不存在,但我们会根据有限状态机的概念编写一个示例)。

假设的yafsm插件使用示例

  1. 定义状态: 首先,我们定义应用中的可能状态。例如,我们有一个简单的计数器应用,它有“idle”、“counting”和“paused”三个状态。
enum CounterState { idle, counting, paused }
  1. 创建状态机: 接下来,我们创建一个简单的状态机类,它将包含状态转换的逻辑。
class CounterStateMachine {
  CounterState _currentState = CounterState.idle;

  CounterState get currentState => _currentState;

  void startCounting() {
    if (_currentState == CounterState.idle || _currentState == CounterState.paused) {
      _currentState = CounterState.counting;
      print("State changed to counting");
    } else {
      print("Cannot start counting from the current state");
    }
  }

  void pauseCounting() {
    if (_currentState == CounterState.counting) {
      _currentState = CounterState.paused;
      print("State changed to paused");
    } else {
      print("Cannot pause from the current state");
    }
  }

  void reset() {
    _currentState = CounterState.idle;
    print("State reset to idle");
  }
}
  1. 在Flutter应用中使用状态机: 最后,我们将这个状态机集成到一个简单的Flutter应用中。
import 'package:flutter/material.dart';

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

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

class CounterScreen extends StatefulWidget {
  @override
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  final CounterStateMachine stateMachine = CounterStateMachine();
  int count = 0;

  void _increment() {
    if (stateMachine.currentState == CounterState.counting) {
      setState(() {
        count++;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter with State Machine'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$count',
              style: Theme.of(context).textTheme.headline4,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                stateMachine.startCounting();
                _increment(); // Simulate counting by incrementing
              },
              child: Text('Start/Increment'),
            ),
            ElevatedButton(
              onPressed: () {
                stateMachine.pauseCounting();
                // No action needed here for pause, just state change
              },
              child: Text('Pause'),
            ),
            ElevatedButton(
              onPressed: () {
                stateMachine.reset();
                setState(() {
                  count = 0;
                });
              },
              child: Text('Reset'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Print current state for debugging
          print('Current state: ${stateMachine.currentState}');
        },
        tooltip: 'Debug State',
        child: Icon(Icons.debug),
      ),
    );
  }
}

说明

  • 状态定义CounterState枚举定义了应用的可能状态。
  • 状态机CounterStateMachine类包含了状态转换的逻辑。
  • Flutter应用CounterScreen是一个简单的Flutter应用,它使用CounterStateMachine来管理按钮点击和状态显示。

请注意,这个示例是基于对“yafsm”名称的推测而创建的,并不是一个真实存在的插件的使用说明。在实际开发中,如果确实存在名为“yafsm”的Flutter插件,你应该查阅其官方文档以获取准确的使用方法和API参考。

回到顶部