[Flutter state management] Bloc pattern_1

Kyuhyeon Kim's avatar
Mar 20, 2024
[Flutter state management] Bloc pattern_1
Reasons for usage:
  1. It allows easy separation of view and business logic.
  1. It is easy to test and reusable.
  1. It enables centralized management of event tracking.
  1. Many developers can work with one codebase. Due to predefined rules, development follows the same pattern, resulting in improved work efficiency.
About Future Used to perform asynchronous tasks Use to obtain data through API communication
About Stream How to process data sequentially by letting it flow (understand it as a subscription concept)

Sort of Bloc widget

  • BlocBuilder - Essential Widget
  • BlocSelector
  • BlocProvider - Essential Widget
  • BlocListner - Essential Widget
  • BlocConsumer
  • RepositoryProvider - Essential Widget
  • MultiRepositoryProvider - Essential Widget


The wiget to provide Bloc
return BlocProvider( create: (context) => SampleBloc(), lazy: false, child: SamplePage(), )
  • Delay generation option (lazy)
  • Accessible from lower layer widgets
  • It automatically returns memory after Bloc is created



Multiple registration of BlocProvider
return MultiBlocProvider( providers: [ BlocProvider( create: (context) => BlocA()), BlocProvider( create: (context) => BlocB()), BlocProvider( create: (context) => BlocC()), ], child: const ChildA(), )



Widgets to use when using bloc created with BlocProvider
  • When using without using the -bloc option, find the bloc from the current context and detect the change.
  • Recommended for use in special cases with -bloc designated cases
@override Widget build(BuildContext context) { sampleBloc = context.read<SampleBloc>(); return Scaffold( body: Center( child: BlocBuilder<SampleBloc, int>( buildWhen: (previous, current) { return current > 10; }, builder: (context, state) { return Text( 'index : $state', style: const TextStyle(fontSize: 70), ); }, ), ),
-The buildWhen option allows you to make changes only when necessary.


RepositoryProvider, MultiRepositoryProvider

Repository + Provider, Widget that provides Repository
  • It may be managed through a delay generation option (lazy).
  • Used for management, such as database or external API communication that can process storage data.
class RepositoryProviderPage extends StatefulWidget { const RepositoryProviderPage({super.key}); @override State<RepositoryProviderPage> createState() => _RepositoryProviderPageState(); } class _RepositoryProviderPageState extends State<RepositoryProviderPage> { @override Widget build(BuildContext context) { return RepositoryProvider( create: (context) => RepositorySample(), child: BlocProvider( create: (context) => SampleBlocDI(context.read<RepositorySample>()), child: SamplePage(), ), ); } }



Widgets to help you make changes by selectivity filtering only the necessart parts of Bloc’s state
BlocSelector<BlocSelectorBloc, BlocSelectorState, bool>( selector: (state) => state.changeState, builder: (context, state) { print('selector builder'); return Icon( Icons.favorite, color: state ? Colors.red : Colors.grey, size: 50, ); }, ), BlocBuilder<BlocSelectorBloc, BlocSelectorState>( buildWhen: (previous, current) => current.changeState, builder: (context, state) { print('bloc builder'); return Text( state.value.toString(), style: const TextStyle(fontSize: 70), ); }, ),


BlocListener, MultiBlocListener

The widget when you only need to handle a event that the changed state
*child widget cannot be rebuild
body: Center( child: BlocListener<SampleBloc, int>( listenWhen: (previous, current) => current > 5, listener: (context, state) { _showMessage(context); }, child: BlocBuilder<SampleBloc, int>( buildWhen: (previous, current) => current > 5, builder: (context, state) { return Text( state.toString(), style: const TextStyle(fontSize: 70), ); }), ),
The situation that you need to show message popup when a certain state have been changed.
When you need to communicate between Blocs



The widget that mixed BlocBuilder and BlocListener
  • Used to process events and change the screen at the same time
  • BuildWhen and listenWhen conditions allow changes and event processing only when appropriate.
Widget build(BuildContext context) { return Scaffold( body: Center( child: BlocConsumer<SampleBloc, int>( listenWhen: (previous, current) => current > 5, listener: (context, state) { _showMessage(context); }, buildWhen: (previous, current) => current % 2 == 0, builder: (context, state) => Text( state.toString(), style: const TextStyle(fontSize: 70), ), ), ), floatingActionButton: FloatingActionButton( onPressed: () { context.read<SampleBloc>().add(AddSampleEvent()); }, ), ); }

Share article
RSSPowered by inblog