state_graph_bloc 1.0.1 state_graph_bloc: ^1.0.1 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".
SingleLiveEventSubject<String> _actionEvent;
Stream<SingleLiveEvent<String>> action;
DummyBloc() : super(StateInitialising()) {
_actionEvent = singleLiveEventSubject();
action = _actionEvent.stream;
}
@override
StateGraph<DummyEvent, DummyState> buildGraph() =>
StateGraph<DummyEvent, DummyState>(
{
StateInitialising: {
LoadEvent: transitionWithSideEffect(
(state, event) => StateLoading(),
(state, event) {
// Call single live events
_actionEvent.add("sample-event-data");
// Add events as a side effects
add(LoadingCompletedEvent());
},
),
},
StateLoading: {
LoadingCompletedEvent: transition((state, event) => StateReady(0)),
},
StateReady: {
IncrementEvent: transition(
(StateReady state, event) => StateReady(state.counter + 1),
),
// Test global event override.
RestartEvent: transition((state, event) => StateReady(0)),
},
},
{
RestartEvent: transition((state, event) {
return StateInitialising();
})
},
);
Stream<bool> isLoading() => bindState((state) {
if (state is StateLoading) {
return true;
} else {
return false;
}
});
}
// Listen to BLoC state.
void main() {
final bloc = DummyBloc();
// Access current state.
bloc.state;
// Listen to bloc (stream) updates.
bloc.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());
}