Using BLoC in Flutter Redux

Using BLoC in Flutter Redux

After using flutter for some time, it seems there are no the go-to way to handle ... Bloc /// /// like reducers in redux, but don't return a new state.

State management is a huge issue for the Flutter community. Coming from an Angular background I got accustomed to using Redux and therefore it made sense for me to follow the same pattern in Flutter. I also used services to encapsulate business logic and expose the state to the UI. It was a good exercise for me to try and emulate the same architecture in Flutter, especially with the emerging of the BLoC pattern.

The following article is my personal take on the matter, I don’t claim it to be the only way of achieving this architecture.

The BLoC pattern

The Business Logic Component pattern or as it is widely known the BLoC pattern is an architecture designed to decouple business logic from the view. It has helped teams to have a single codebase in regards to their business logic and expose them in various frameworks, most notable AngularDart and Flutter

In the BLoC pattern, you create a component that interfaces with the view only through Streams. This goes for all interaction either coming into the BLoC or coming out of it. The outgoing communication is straight forward as you only need to wrap your view Widget in a StreamBuilder and listen to the values coming out of the exposed outgoing stream.

class ExampleBloc {
	 final StreamController<int> _outController =  StreamController<int>();
	  
	  int get out => _outController.stream;
	}
	

	...
	  
	StreamBuilder<int>(
	  stream: exampleBloc.out
	  builder: (context, snapshot) {
	    if (!snapshot.hasData) {
	      return Container();
	    }
	    final out = snapshot.data;
	    return Text('$out');
	  }
	)

For the incoming communication, you have to also expose a Sink in which the view will push events from the user. In your BLoC, you subscribe to the incoming Stream and delegate the action either to a private method or a Repository, if it is about fetching data.

class ExampleBloc {
	 int counter = 0;
	 final StreamController<int> _incrementController =  StreamController<int>();
	 final StreamController<int> _outController =  StreamController<int>();
	 
	 ExampleBloc() {
	    _outController.sink.add(counter);
	    _incrementController.listen(_incrementBy);
	  }
	 
	 /// Do the actions or delegate in a repository
	 void _incrementBy(int value) {
	   counter += value;
	   //Notify subscribers
	   _outController.sink.add(counter);
	 }
	  
	  int get out => _outController.stream;
	  int get incrementBy => _incrementController.sink;
	}
	

	...
	  
	FloatingActionButton(
	  onPressed: () => exampleBloc.incrementBy.add(1),
	  tooltip: 'Increment By 1',
	)

What remains to be tackled is the state keeping as we really do not want to keep it in our BLoC.

Redux Store with BLoC

As we mentioned before the BLoC should not be responsible to keep the application’s state. It should delegate this responsibility to some other component dedicated to doing state management. In this example, we will use the Redux Store.

The BLoC could funnel events coming from the Sink to the Store as Actions and connect the application state from the Store to the Stream so that the Widget gets it.

/// The action to be dispatched from the BLoC to the Store
	class IncrementByAction {
	  final int value;
	  const IncrementByAction(this.value);
	}
	

	/// The state of the application as it is managed by the Store
	class AppState {
	  final int counter;
	  
	  const AppState(this.counter);
	  
	  factory AppState.initial() => AppState(0);
	  
	  AppState incrementBy(int value) => AppState(counter+value);
	}
	

	final store = new Store<AppState>(
	  TypedReducer<AppState, ChangeLocaleAction>((AppState state, IncrementByAction action) => state.incrementBy(action.value)),
	  initialState: AppState.initial(),
	  middleware: [],
	);
	

	/// The BLoC delegates all state management to the Store
	class ExampleBloc {
	 final Store<AppState> store;
	 final StreamController<int> _incrementController =  StreamController<int>();
	 
	 ExampleBloc(this.store) {
	   _incrementController.listen(_incrementBy);
	 }
	  
	 /// Dispatch the Store Action to change the AppState
	 void _incrementBy(int value) {
	   store.dispatch(IncrementByAction(value));
	 }
	  
	  /// To connect the state from the store to the ougoing stream of the BLoC subscribe to store.onChange
	  int get out => this.store.onChange.map((AppState state) => state.counter);
	  int get incrementBy => _incrementController.sink;
	}
	/*
	 * No changes are needed in the UI as the BLoC's api did not change.
	 */
	...
	FloatingActionButton(
	  onPressed: () => exampleBloc.incrementBy.add(1),
	  tooltip: 'Increment By 1',
	)
	...
	StreamBuilder<int>(
	  stream: exampleBloc.out
	  builder: (context, snapshot) {
	    if (!snapshot.hasData) {
	      return Container();
	    }
	    final out = snapshot.data;
	    return Text('$out');
	  }
	)

The obvious benefit of using this approach is that if you do not have to change the BLoC’s API and thus no change in the UI (Widgets) is needed.

However, there is another approach that kind of breaks the BLoC all Streams contract. It uses methods for actions and getters for state subscribing. It is all made possible by the use of StoreConnector.

/// The action to be dispatched from the BLoC to the Store
	class IncrementByAction {
	  final int value;
	  const IncrementByAction(this.value);
	}
	

	/// The state of the application as it is managed by the Store
	class AppState {
	  final int counter;
	  
	  const AppState(this.counter);
	  
	  factory AppState.initial() => AppState(0);
	  
	  AppState incrementBy(int value) => AppState(counter+value);
	}
	

	final store = new Store<AppState>(
	  TypedReducer<AppState, ChangeLocaleAction>((AppState state, IncrementByAction action) => state.incrementBy(action.value)),
	  initialState: AppState.initial(),
	  middleware: [],
	);
	

	/// The BLoC acts like a proxy to the store
	class ExampleBloc {
	 final Store<AppState> store;
	 
	 ExampleBloc(this.store);
	  
	  /// To connect the state from the store to the ougoing stream of the BLoC subscribe to store.onChange
	  int get counter => this.store.state.counter;
	  void incrementBy(int value) {
	      store.dispatch(IncrementByAction(value));
	  }
	}
	...
	StoreConnector<AppState, DebtorBloc>(
	    converter: (store) => ExampleBloc(store),
	    builder: (BuildContext context, ExampleBloc bloc) {
	      return FloatingActionButton(
	        onPressed: () => exampleBloc.incrementBy(1),
	        tooltip: 'Increment By 1',
	      );
	    }
	)
	...
	StoreConnector<AppState, DebtorBloc>(
	    converter: (store) => ExampleBloc(store),
	    builder: (BuildContext context, ExampleBloc bloc) {
	      final out = bloc.counter;
	      return Text('$out');
	    }
	)

The BLoC pattern is a great way to encapsulate business logic and Redux is a great state management paradigm. Combining the two of them can create a clean logic layer in your application, which is going to help you tremendously in creating clean UI code.

ECommerce Mobile App Development | Ecommerce Mobile App Development Services

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates. **Know about [Top ECommerce Mobile App Development...

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates.

Know about Top ECommerce Mobile App Development Company

ECommerce Mobile App Development Company in England

ECommerce Mobile App Development Company in England

At [**WebClues Global**](https://www.webcluesglobal.com/ "WebClues Global") we have been working on eCommerce apps for the last 7+ years and have built systems which are secure, reliable and easy to use. We have people who have good knowledge on a...

At WebClues Global we have been working on eCommerce apps for the last 7+ years and have built systems which are secure, reliable and easy to use. We have people who have good knowledge on a wide variety of ecommerce technologies – Magento eCommerce, WooCommerce, Shopify, Drupal Commerce, OpenCart, BigCommerce, Joomla , Prestashop, NopCommerce.

As a top ECommerce Mobile App Development Company in England, We have been in the business of software develop ment for 7+ years and we are a specialist in Team Software Development by following Agile Methods. We provide a range of services on eCommerce app development with the support of our deep web application development and mobile app development expertise.

Trending Mobile App Ideas For Business

Trending Mobile App Ideas For Business

If you are finding the latest and innovative app ideas then look no further. Here, we explain 50+ trending mobile app ideas for business that will make money in 2020 and beyond.

If you are finding the latest and innovative app ideas then look no further. Here, we explain 50+ trending mobile app ideas for business that will make money in 2020 and beyond.