### Official Bloc vs StreamBloc Counter Example (Dart) Source: https://github.com/purplenoodlesoop/stream-bloc/blob/master/README.md Demonstrates the translation of an official Bloc implementation using the 'on' method to a StreamBloc implementation using the 'mapEventToStates' method. This example showcases how to handle Increment and Decrement events for a counter. ```dart abstract class CounterEvent {} // Shared counter event type class Increment implements CounterEvent {} class Decrement implements CounterEvent {} class OnCounterBloc extends Bloc { // Official Bloc – `on`s OnCounterBloc() : super(0) { on((event, emit) => emit(state + 1)); on((event, emit) => emit(state - 1)); } } class StreamCounterBloc extends StreamBloc { // StreamBloc – `mapEventToStates` StreamCounterBloc() : super(0); @override Stream mapEventToStates(CounterEvent event) async* { if (event is Increment) { yield state + 1; } else if (event is Decrement) { yield state - 1; } } } ``` -------------------------------- ### StreamBloc Lifecycle Hooks Example in Dart Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt Demonstrates how to use onEvent, onChange, onTransition, and onError lifecycle hooks in a StreamBloc to monitor and react to bloc activities. This example shows custom logging for events, state changes, transitions, and errors. ```dart import 'package:stream_bloc/stream_bloc.dart'; class UserEvent { final String action; const UserEvent(this.action); } class UserState { final String status; final int actionCount; const UserState(this.status, this.actionCount); @override String toString() => 'UserState($status, count: $actionCount)'; } class UserBloc extends StreamBloc { UserBloc() : super(UserState('idle', 0)); @override void onEvent(UserEvent event) { super.onEvent(event); print('📥 Event received: ${event.action}'); } @override void onChange(Change change) { super.onChange(change); print('📊 State changing: ${change.currentState} -> ${change.nextState}'); } @override void onTransition(Transition transition) { super.onTransition(transition); print('🔄 Transition: ${transition.event.action} caused ${transition.nextState}'); } @override void onError(Object error, StackTrace stackTrace) { print('❌ Error occurred: $error'); super.onError(error, stackTrace); } @override Stream mapEventToStates(UserEvent event) async* { final newCount = state.actionCount + 1; if (event.action == 'login') { yield UserState('authenticating', newCount); await Future.delayed(Duration(seconds: 1)); yield UserState('authenticated', newCount); } else if (event.action == 'logout') { yield UserState('logging_out', newCount); await Future.delayed(Duration(milliseconds: 500)); yield UserState('idle', newCount); } } } // Usage with comprehensive logging void main() async { final bloc = UserBloc(); bloc.stream.listen((state) => print('UI Update: $state')); bloc.add(UserEvent('login')); await Future.delayed(Duration(milliseconds: 1500)); bloc.add(UserEvent('logout')); await Future.delayed(Duration(seconds: 1)); await bloc.close(); } ``` -------------------------------- ### StreamBloc Example: Counter State Management Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt Demonstrates the core `StreamBloc` class for managing state with increment and decrement events. It utilizes `mapEventToStates` to transform events into a stream of integer states, starting with an initial state of 0. Usage involves creating a `StreamBloc` instance, listening to its state stream, and adding events. ```dart import 'package:stream_bloc/stream_bloc.dart'; // Define events abstract class CounterEvent {} class Increment implements CounterEvent {} class Decrement implements CounterEvent {} // Create a StreamBloc class CounterBloc extends StreamBloc { CounterBloc() : super(0); // Initial state is 0 @override Stream mapEventToStates(CounterEvent event) async* { if (event is Increment) { yield state + 1; } else if (event is Decrement) { yield state - 1; } } } // Usage void main() async { final bloc = CounterBloc(); // Listen to state changes bloc.stream.listen((state) => print('Current count: $state')); // Add events bloc.add(Increment()); // Output: Current count: 1 bloc.add(Increment()); // Output: Current count: 2 bloc.add(Decrement()); // Output: Current count: 1 await Future.delayed(Duration(milliseconds: 100)); await bloc.close(); } ``` -------------------------------- ### Implement Global Bloc Monitoring with StreamBlocObserver Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt StreamBlocObserver allows for global monitoring of bloc lifecycle events such as creation, event dispatch, state changes, transitions, and errors. It can be injected statically or via zones. This example demonstrates a LoggingObserver that prints these events to the console. ```dart import 'package:stream_bloc/stream_bloc.dart'; class LoggingObserver extends StreamBlocObserver { @override void onCreate(Closable closable) { super.onCreate(closable); print('Created: ${closable.runtimeType}'); } @override void onEvent(BlocEventSink eventSink, Object? event) { super.onEvent(eventSink, event); print('Event: $event in ${eventSink.runtimeType}'); } @override void onChange( StateStreamable stateStreamable, Change change, ) { super.onChange(stateStreamable, change); print('Change: ${change.currentState} -> ${change.nextState}'); } @override void onTransition( BlocEventSink bloc, Transition transition, ) { super.onTransition(bloc, transition); print('Transition: ${transition.event} -> ${transition.nextState}'); } @override void onError(ErrorSink errorSink, Object error, StackTrace stackTrace) { super.onError(errorSink, error, stackTrace); print('Error: $error'); } } // Setup observer void main() async { // Set global observer StreamBlocObserver.current = LoggingObserver(); final bloc = CounterBloc(); bloc.add(Increment()); // Triggers onEvent, onTransition, onChange await Future.delayed(Duration(milliseconds: 100)); await bloc.close(); } class Increment {} class CounterBloc extends StreamBloc { CounterBloc() : super(0); @override Stream mapEventToStates(Increment event) async* { yield state + 1; } } ``` -------------------------------- ### Control Stream Flow with StreamBloc Transformers Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt StreamBloc offers three stream transformers: `transformSourceEvents` for preprocessing incoming events, `transformEvents` for controlling event-to-state mapping, and `transformTransitions` for manipulating outgoing state changes. This example uses these transformers to throttle search events, cancel previous searches, and debounce state changes. ```dart import 'package:stream_bloc/stream_bloc.dart'; class SearchEvent { final String query; const SearchEvent(this.query); } class SearchBloc extends StreamBloc { SearchBloc() : super(''); // Throttle incoming search events @override Stream transformSourceEvents(Stream events) { return events.distinct((prev, next) => prev.query == next.query) .asyncExpand((event) async* { await Future.delayed(Duration(milliseconds: 300)); yield event; }); } // Use switchMap to cancel previous searches @override Stream> transformEvents( Stream events, TransitionFunction transitionFn, ) { return events.asyncExpand((event) => transitionFn(event)); } // Debounce state changes @override Stream> transformTransitions( Stream> transitions, ) { return transitions; } @override Stream mapEventToStates(SearchEvent event) async* { if (event.query.isEmpty) { yield ''; } else { // Simulate API call await Future.delayed(Duration(milliseconds: 500)); yield 'Results for: ${event.query}'; } } } // Usage void main() async { final bloc = SearchBloc(); bloc.stream.listen((result) => print(result)); // Rapid-fire events are throttled bloc.add(SearchEvent('a')); bloc.add(SearchEvent('ap')); bloc.add(SearchEvent('app')); bloc.add(SearchEvent('appl')); bloc.add(SearchEvent('apple')); await Future.delayed(Duration(seconds: 2)); await bloc.close(); } ``` -------------------------------- ### BlocLifecycleMixin Usage in Dart Source: https://github.com/purplenoodlesoop/stream-bloc/blob/master/README.md Demonstrates how to use the BlocLifecycleMixin with a StreamBloc. It shows setting up event handling, reacting to a periodic stream, and listening to the bloc's own stream for side effects. The mixin simplifies stream subscription management. ```dart class IncrementEvent { final int amount; const IncrementEvent(this.amount); } class IncrementBloc extends StreamBloc with BlocLifecycleMixin { IncrementBloc() : super(0) { reactToStream( Stream.periodic(const Duration(seconds: 1), (i) => i), (passed) => IncrementEvent(passed), ); listenToStream( stream, print, ); } @override Stream mapEventToStates(IncrementEvent event) => Stream.value( state + event.amount, ); } ``` -------------------------------- ### StreamBloc: Data Loading with State Transitions Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt Illustrates `StreamBloc` for handling data loading states (initial, loading, loaded, error). The `mapEventToStates` method simulates asynchronous data fetching, yielding different states based on the operation's success or failure. It includes basic error handling for the loading process. ```dart import 'package:stream_bloc/stream_bloc.dart'; class LoadDataEvent {} class RefreshDataEvent {} enum DataState { initial, loading, loaded, error } class DataBloc extends StreamBloc { DataBloc() : super(DataState.initial); @override Stream mapEventToStates(dynamic event) async* { if (event is LoadDataEvent) { yield DataState.loading; try { // Simulate async data loading await Future.delayed(Duration(seconds: 2)); yield DataState.loaded; } catch (e) { yield DataState.error; } } else if (event is RefreshDataEvent) { yield DataState.loading; await Future.delayed(Duration(seconds: 1)); yield DataState.loaded; } } } // Usage with error handling void main() async { final bloc = DataBloc(); bloc.stream.listen( (state) => print('State: $state'), onError: (error) => print('Error: $error'), ); bloc.add(LoadDataEvent()); await Future.delayed(Duration(seconds: 3)); await bloc.close(); } ``` -------------------------------- ### BlocLifecycleMixin: Automated Stream Subscription Management Source: https://context7.com/purplenoodlesoop/stream-bloc/llms.txt Showcases `BlocLifecycleMixin` for managing stream subscriptions within a `StreamBloc`. It provides `listenToStream` for reacting to stream events and `reactToStream` for converting external stream emissions into bloc events. All subscriptions managed by the mixin are automatically canceled when the bloc is closed. ```dart import 'dart:async'; import 'package:stream_bloc/stream_bloc.dart'; class TickEvent { final int count; const TickEvent(this.count); } class TimerBloc extends StreamBloc with BlocLifecycleMixin { TimerBloc() : super(0) { // React to external stream by converting to events reactToStream( Stream.periodic(Duration(seconds: 1), (i) => i), (tick) => TickEvent(tick), ); // Listen to own state changes listenToStream( stream, (state) => print('Timer: $state seconds'), ); } @override Stream mapEventToStates(TickEvent event) async* { yield event.count; } } // Usage - subscriptions auto-cancel on close void main() async { final bloc = TimerBloc(); await Future.delayed(Duration(seconds: 5)); await bloc.close(); // Automatically cancels all subscriptions } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.