Last active
February 12, 2022 16:45
-
-
Save dnys1/cd3df1fe5cb649ee82c47919b9fe4549 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
void main() { | |
final stateMachine = MyStateMachine(); | |
// Dispatch three events synchronously. Notice how they are processed. | |
stateMachine.dispatch(MyEvent()); | |
stateMachine.dispatch(MyEvent()); | |
stateMachine.dispatch(MyEvent()); | |
} | |
class MyStateMachine extends StateMachine<MyEvent, MyState> { | |
@override | |
MyState get initialState => MyState(0); | |
@override | |
Stream<MyState> transformEvent(MyEvent event) async* { | |
yield MyState(currentState.i + 1); | |
await Future.delayed(const Duration(seconds: 2)); | |
yield MyState(currentState.i + 1); | |
} | |
} | |
class MyState extends State { | |
MyState(this.i); | |
final int i; | |
@override | |
String toString() => '$i'; | |
} | |
class MyEvent extends Event { | |
@override | |
bool meetsPrecondition(MyState currentState) { | |
return true; | |
} | |
} | |
abstract class Event { | |
/// Whether the event can be processed given the [currentState] | |
/// of the state machine. | |
bool meetsPrecondition(covariant State currentState); | |
} | |
abstract class State {} | |
abstract class StateMachine<E extends Event, S extends State> { | |
StateMachine() { | |
_eventController.stream.asyncExpand((event) { | |
if (!event.meetsPrecondition(_currentState)) { | |
print('Skipping $event'); | |
return Stream<S>.empty(); | |
} | |
return transformEvent(event); | |
}).listen((state) { | |
print('Transitioning from $_currentState to $state'); | |
_stateController.add(state); | |
_currentState = state; | |
}); | |
} | |
final StreamController<E> _eventController = StreamController.broadcast(); | |
final StreamController<S> _stateController = StreamController.broadcast(); | |
/// The state machine's initial state. | |
S get initialState; | |
late S _currentState = initialState; | |
/// The state machine's current state. | |
S get currentState => _currentState; | |
/// The stream of states. | |
Stream<S> get stream => _stateController.stream; | |
/// Dispatches an event to the state machine. | |
void dispatch(E event) => _eventController.add(event); | |
/// Transforms events into a stream of state changes. | |
Stream<S> transformEvent(E event); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment