state_graph_bloc 5.0.0 state_graph_bloc: ^5.0.0 copied to clipboard
A bloc package with concise state graph builder. Build transitions, side effects and global events in a centralised, type-safe manner.
import 'package:state_graph_bloc/state_graph_bloc.dart';
// Enumerate states.
abstract class DummyState {}
class StateInitialising extends DummyState {
@override
bool operator ==(Object other) => hashCode == other.hashCode;
@override
int get hashCode => runtimeType.hashCode;
}
class StateLoading extends DummyState {
@override
bool operator ==(Object other) => hashCode == other.hashCode;
@override
int get hashCode => runtimeType.hashCode;
}
class StateReady extends DummyState {
StateReady(this.counter);
final int counter;
@override
bool operator ==(Object other) => hashCode == other.hashCode;
@override
int get hashCode => runtimeType.hashCode ^ counter.hashCode;
}
// Enumerate events
abstract class DummyEvent {}
class LoadEvent extends DummyEvent {}
class LoadingCompletedEvent extends DummyEvent {}
class LoadingErrorEvent extends DummyEvent {}
class IncrementEvent extends DummyEvent {}
class SideEffectCauseEvent extends DummyEvent {}
class RestartEvent extends DummyEvent {}
// Define bloc with graph transitions
class DummyBloc extends StateGraphBloc<DummyEvent, DummyState> {
// Create "single live events".
late SingleLiveEventSubject<String> _actionEvent;
late Stream<SingleLiveEvent<String>> action;
DummyBloc() : super(StateInitialising()) {
_actionEvent = singleLiveEventSubject();
action = _actionEvent.stream;
}
@override
StateGraph<DummyEvent, DummyState> buildGraph() =>
StateGraph<DummyEvent, DummyState>(
{
StateInitialising: {
LoadEvent: transitionWithSideEffect(
(dynamic state, dynamic event) => StateLoading(),
(dynamic state, dynamic event) {
// Call single live events
_actionEvent.add('sample-event-data');
// Add events as a side effects
add(LoadingCompletedEvent());
},
),
},
StateLoading: {
LoadingCompletedEvent:
transition((dynamic state, dynamic event) => StateReady(0)),
},
StateReady: {
IncrementEvent: transition(
(StateReady state, dynamic event) =>
StateReady(state.counter + 1),
),
// Test global event override.
RestartEvent:
transition((dynamic state, dynamic event) => StateReady(0)),
},
},
globalEvents: {
RestartEvent: transition((dynamic state, dynamic event) {
return StateInitialising();
})
},
);
Stream<bool> isLoading() => bindState((state) {
if (state is StateLoading) {
return true;
} else {
return false;
}
});
}
// Listen to BLoC state.
void main() async {
final bloc = DummyBloc();
// Access current state stream.
await bloc.state.first;
// Listen to bloc (stream) updates.
bloc.state.listen((state) => print('On state change'));
// Listen to bloc field updates.
bloc
.isLoading()
.listen((isLoading) => print('Is currently loading: $isLoading'));
// Listen to bloc single live events.
// Call `use` to consume and receive event data.
bloc.action.listen((event) {
event.use((it) => print('Event received: $it'));
});
// Add events.
bloc.add(LoadEvent());
}