Comment on page
Trigger a Transition
Once you have a FSM you need to trigger a transition to a new state.
This is done with the
StateMachine().applyEvent
method.var machine = StateMachine.create((g) => g
..initialState<Solid>()
..state<Solid>((b) => b
..on<OnMelted, Liquid>(
sideEffect: (e) => watcher.log(onMeltedMessage))
..onEnter((s, e) => watcher?.onEnter(s))
..onExit((s, e) => watcher?.onExit(s)))
..state<Liquid>((b) => b
..onEnter((s, e) => watcher?.onEnter(s))
..onExit((s, e) => watcher?.onExit(s))
..on<OnFroze, Solid>(
sideEffect: (e) => watcher.log(onFrozenMessage))
..on<OnVaporized, Gas>(
sideEffect: (e) => watcher.log(onVaporizedMessage)))
..state<Gas>((b) => b..on<OnCondensed, Liquid>(
sideEffect: (e) => watcher.log(onCondensedMessage)))
);
machine.applyEvent(OnFroze());
The
applyEvent
method takes an Event and may cause the FSM to transition to a new state.If you have concurrent regions or nested states then a single event may result in multiple transitions.
You should be aware that some calls to `applyEvent` will not result in a change in State. This can happen due to Guard Conditions suppressing the transition.
Calls to
StateMachine.applyEvent
are asynchronous. Your state machine will not have finished transitioning when applyEvent returns! Use an onEnter, onExit, sideEffect or stream to get notifications of when the statemachine has entered a new state.
Calls to
StateMachine.applyEvent
can be made at any time and from any code. The StateMachine will queue any events and only apply the event once any active or pre existing queued events have completed.
If you call applyEvent with an event you must be in a state that has an handler for that event.
final machine = StateMachine.create((g) => g
..initialState<Solid>()
..state<Solid>((b) => b
..on<OnMelted, Liquid>(sideEffect: (e) async => print('Melted'))
..state<Liquid>((b) => b
..on<OnFroze, Solid>(sideEffect: (e) async => print('Frozen'))
..on<OnVaporized, Gas>(sideEffect: (e) async => print('Vaporized')))
..state<Gas>((b) => b
..on<OnCondensed, Liquid>(sideEffect: (e) async => print('Condensed'))));
machine.applyEvent(OnFroze());
The above call to 'machine.applyEvent' will fail as the initialState is 'Solid' and the 'Solid' state doesn't have a handler for the 'OnFroze' event.
Note: FSM2 supports inherited transition handlers so an event can be processed if an active State OR one of its parents has a handler for the state.
If the statemachine is can't handle the event then a 'InvalidTransitionException' is thrown.
The exception is thrown only when in debug mode. If you pass 'production: true' to the statemachine 'create' method then the exception will be suppressed and instead it will be logged. This is done to make the FSM less brittle in production.
If you have concurrent regions in you FSM and a concurrent region is active when an event is applied, only one of the active states needs to be able to handle the event. If at least on of the actives states handles the event then an 'InvalidTransitionException' will not be thrown.
Last modified 2yr ago