Flutter插件hisma_flutter的探索使用
Flutter插件hisma_flutter的探索使用
Flutter插件hisma_flutter的特性
- 将屏幕创建器映射到状态
- 将覆盖屏幕创建器映射到状态
- 将对话框创建器映射到状态
- 将实用程序创建器([NoUIChange])映射到状态
- 支持层次结构 - 嵌套导航
示例演示
在以下示例中,我们将逐步展示如何使用hisma_flutter
插件来构建一个具有不同功能的应用程序。
最小应用:单页面
让我们创建一个最简单的hisma_flutter
应用程序,该应用程序包含一个单一状态机和一个映射到此状态的单一屏幕。
状态机声明
enum S { a }
enum E { e1 }
enum T { t1 }
final machine = StateMachineWithChangeNotifier<S, E, T>(
initialStateId: S.a,
name: 'machine',
states: {
S.a: hisma.State(),
},
transitions: {},
);
屏幕定义
class Screen extends StatelessWidget {
const Screen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Screen')),
);
}
}
屏幕与状态映射
final hismaRouterGenerator = HismaRouterGenerator<S, Widget, E>(
machine: machine,
creators: {S.a: MaterialPageCreator<S>(widget: const Screen())},
);
配置主Widget
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: hismaRouterGenerator.routerDelegate,
routeInformationParser: hismaRouterGenerator.routeInformationParser,
);
}
}
启动状态机
Future<void> main() async {
hisma.StateMachine.monitorCreators = [
(m) => VisualMonitor(m),
];
await machine.start();
runApp(const MyApp());
}
简单应用:三页面
接下来,我们创建一个包含三个状态和三个屏幕的应用程序。
状态机声明
enum S { a, b, c }
enum E { forward, backward }
enum T { toA, toB, toC }
final machine = StateMachineWithChangeNotifier<S, E, T>(
events: E.values,
initialStateId: S.a,
name: 'machine',
states: {
S.a: hisma.State(
etm: {
E.forward: [T.toB],
},
),
S.b: hisma.State(
etm: {
E.forward: [T.toC],
E.backward: [T.toA],
},
),
S.c: hisma.State(
etm: {
E.backward: [T.toB],
},
),
},
transitions: {
T.toA: hisma.Transition(to: S.a),
T.toB: hisma.Transition(to: S.b),
T.toC: hisma.Transition(to: S.c),
},
);
屏幕定义
class ScreenA extends StatelessWidget {
const ScreenA({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ScreenA')),
body: createButtonsFromStates([machine.states[S.a]]),
);
}
}
class ScreenB extends StatelessWidget {
const ScreenB({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ScreenB')),
body: createButtonsFromStates([machine.states[S.b]]),
);
}
}
class ScreenC extends StatelessWidget {
const ScreenC({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ScreenC')),
body: createButtonsFromStates([machine.states[S.c]]),
);
}
}
屏幕与状态映射
final hismaRouterGenerator = HismaRouterGenerator<S, Widget, E>(
machine: machine,
creators: {
S.a: MaterialPageCreator<S>(widget: const ScreenA()),
S.b: MaterialPageCreator<S>(widget: const ScreenB()),
S.c: MaterialPageCreator<S>(widget: const ScreenC()),
},
);
使用覆盖页面
在本节中,我们将使用覆盖页面。这将导致ScreenC
堆叠在ScreenB
上,而ScreenB
又堆叠在ScreenA
上。
映射屏幕到状态
final hismaRouterGenerator = HismaRouterGenerator<S, Widget, E>(
machine: machine,
creators: {
S.a: MaterialPageCreator<S>(widget: const ScreenA()),
S.b: OverlayMaterialPageCreator<S, E>(
widget: const ScreenB(),
event: E.backward,
),
S.c: OverlayMaterialPageCreator<S, E>(
widget: const ScreenC(),
event: E.backward,
),
},
);
对话框
在这一部分中,我们将扩展之前的状态机以包括两个新的状态:b1
表示一个AboutDialog
,c1
表示一个DatePicker
。
新状态机声明
enum S { a, b, b1, c, c1 }
enum E { forward, show, backward }
enum T { toA, toB, toB1, toC, toC1 }
final machine = StateMachineWithChangeNotifier<S, E, T>(
events: E.values,
initialStateId: S.a,
name: 'machine',
states: {
S.a: hisma.State(
etm: {
E.forward: [T.toB],
},
),
S.b: hisma.State(
etm: {
E.forward: [T.toC],
E.backward: [T.toA],
E.show: [T.toB1],
},
onEntry: getAction(),
),
S.b1: hisma.State(
etm: {
E.backward: [T.toB],
},
),
S.c: hisma.State(
etm: {
E.backward: [T.toB],
E.show: [T.toC1],
},
onEntry: getAction(),
),
S.c1: hisma.State(
etm: {
E.backward: [T.toC],
},
),
},
transitions: {
T.toA: hisma.Transition(to: S.a),
T.toB: hisma.Transition(to: S.b),
T.toB1: hisma.Transition(to: S.b1),
T.toC: hisma.Transition(to: S.c),
T.toC1: hisma.Transition(to: S.c1),
},
);
hisma.Action getAction() => hisma.Action(
description: 'Print out argument passed.',
action: (machine, dynamic arg) async =>
print('Arg passed: $arg'),
);
创建对话框
Future<bool?> b1(BuildContext context) => showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Simple AlertDialog'),
content: const Text('Hello'),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop(true);
},
),
],
);
},
);
Future<DateTime?> c1(BuildContext context) => showDatePicker(
context: context,
firstDate: DateTime(2021),
initialDate: DateTime.now(),
currentDate: DateTime.now(),
lastDate: DateTime(2028),
);
映射屏幕到状态
final hismaRouterGenerator = HismaRouterGenerator<S, Widget, E>(
machine: machine,
creators: {
S.a: MaterialPageCreator<S>(widget: const ScreenA()),
S.b: OverlayMaterialPageCreator<S, E>(
widget: const ScreenB(),
event: E.backward,
),
S.b1: PagelessCreator(show: b1, event: E.backward),
S.c: OverlayMaterialPageCreator<S, E>(
widget: const ScreenC(),
event: E.backward,
),
S.c1: PagelessCreator(show: c1, event: E.backward),
},
);
实用状态
在某些情况下,你可能希望某个状态不映射到任何UI元素。在这种情况下,我们可以使用NoUIChange
创建器。
扩展状态机
S.b2: hisma.State(
etm: {
E.backward: [T.toBFromB2],
},
onEntry: hisma.Action(
description: 'Fetch weather report.',
action: (machine, dynamic arg) async {
Future<void>.delayed(const Duration(seconds: 1), () {
print('Weather data is fetched.');
machine.fire(E.backward, data: 'Sunny weather.');
});
},
),
),
映射屏幕到状态
final hismaRouterGenerator = HismaRouterGenerator<S, Widget, E>(
machine: machine,
creators: {
S.a: MaterialPageCreator<S>(widget: const ScreenA()),
S.b: OverlayMaterialPageCreator<S, E>(
widget: const ScreenB(),
event: E.backward,
),
S.b1: PagelessCreator(show: b1, event: E.backward),
S.b2: NoUIChange(),
S.c: OverlayMaterialPageCreator<S, E>(
widget: const ScreenC(),
event: E.backward,
),
S.c1: PagelessCreator(show: c1, event: E.backward),
},
);
添加层次结构
最后,我们将添加层次结构,以便我们的状态机可以嵌套导航。
状态机声明
enum AS { signedIn, signedOut }
enum AE { signIn, signOut }
enum AT { toSignedIn, toSignedOut }
final authMachine = StateMachineWithChangeNotifier<AS, AE, AT>(
events: AE.values,
name: 'authMachine',
initialStateId: AS.signedOut,
states: {
AS.signedOut: hisma.State(
etm: {
AE.signIn: [AT.toSignedIn],
},
),
AS.signedIn: hisma.State(
etm: {
AE.signOut: [AT.toSignedOut],
},
regions: [
hisma.Region<AS, AE, AT, S>(machine: machine),
],
),
},
transitions: {
AT.toSignedOut: hisma.Transition(to: AS.signedOut),
AT.toSignedIn: hisma.Transition(to: AS.signedIn),
},
);
屏幕定义
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('LoginScreen')),
body: createButtonsFromStates([authMachine.states[AS.signedOut]]),
);
}
}
映射屏幕到状态
final authRouterGenerator = HismaRouterGenerator<AS, Widget, AE>(
machine: authMachine,
creators: {
AS.signedOut: MaterialPageCreator<AS>(widget: const LoginScreen()),
AS.signedIn: MaterialPageCreator<AS>(
widget: Router(routerDelegate: hismaRouterGenerator.routerDelegate),
),
},
);
更多关于Flutter插件hisma_flutter的探索使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter插件hisma_flutter的探索使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
hisma_flutter
是一个基于 Hisma 状态管理库的 Flutter 插件,它允许开发者通过状态机的方式来管理应用的复杂状态。Hisma 是一个轻量级的状态机库,专注于简化状态管理和状态转换的复杂性。hisma_flutter
将这些概念引入到 Flutter 中,使得开发者可以更容易地管理应用的状态。
由于 hisma_flutter
是一个相对较新的插件,可能没有广泛的文档或社区支持,因此在探索和使用时可能需要一些实验和调试。以下是一些基本步骤和概念,帮助你开始使用 hisma_flutter
。
1. 安装 hisma_flutter
首先,你需要在 pubspec.yaml
文件中添加 hisma_flutter
依赖:
dependencies:
flutter:
sdk: flutter
hisma_flutter: ^0.0.1 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 基本概念
hisma_flutter
基于状态机(State Machine)的概念,状态机由以下几个核心部分组成:
- States(状态):应用可以处于的不同状态。
- Events(事件):触发状态转换的事件。
- Transitions(转换):定义状态之间如何转换。
- Actions(动作):在状态转换时执行的操作。
3. 创建一个简单的状态机
假设我们有一个简单的应用,只有两个状态:Idle
和 Active
。
import 'package:hisma_flutter/hisma_flutter.dart';
enum States { idle, active }
enum Events { activate, deactivate }
final stateMachine = StateMachine<States, Events, void>(
initialState: States.idle,
states: {
States.idle: State(
onEntry: [Action(() => print('Entered Idle state'))],
onExit: [Action(() => print('Exited Idle state'))],
),
States.active: State(
onEntry: [Action(() => print('Entered Active state'))],
onExit: [Action(() => print('Exited Active state'))],
),
},
transitions: {
States.idle: {
Events.activate: Transition(to: States.active),
},
States.active: {
Events.deactivate: Transition(to: States.idle),
},
},
);
4. 在 Flutter 中使用状态机
你可以在 Flutter 的 StatefulWidget
中使用这个状态机来管理状态。
import 'package:flutter/material.dart';
import 'package:hisma_flutter/hisma_flutter.dart';
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final StateMachine<States, Events, void> stateMachine;
[@override](/user/override)
void initState() {
super.initState();
stateMachine = createStateMachine(); // 使用之前定义的状态机
stateMachine.start();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Hisma Flutter Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
stateMachine.fire(Events.activate);
},
child: Text('Activate'),
),
ElevatedButton(
onPressed: () {
stateMachine.fire(Events.deactivate);
},
child: Text('Deactivate'),
),
],
),
),
),
);
}
[@override](/user/override)
void dispose() {
stateMachine.stop();
super.dispose();
}
}