Introducing flutter_rx_bloc: Part 3
The flutter_rx_bloc is a Flutter package that exposes your reactive BloCs to the UI Layer. In the previous article, Introducing rx_bloc: Part 2 (I recommend that you read it quickly before continuing with this article if you haven’t already), you learned how you can implement the business layer of the Counter sample and in this article, we’ll see how we can bind it to the UI Layer
Let’s start with what flutter_rx_bloc offers and how it can help us.
RxBlocProvider
RxBlocProvider is a Flutter widget that provides a BloC to its children via RxBlocProvider.of<T>(context). It is used as a dependency injection (DI) widget so that a single instance of a BloC can be provided to multiple widgets within a subtree.
In most cases, RxBlocProvider should be used to create new BloCs which will be made available to the rest of the subtree. At the same time, RxBlocProvider automatically handles closing the BloC as well. This ensures that our BloCs don’t cause any memory leaks.
Let’s now see how we can create an instance of the CounterBloc using RxBlocProvider.
MaterialApp(
...
home: RxBlocProvider<CounterBlocType>(
create: (context) => CounterBloc(CounterRepository()),
child: const HomePage(),
),
);
In case you need to provide multiple BloCs to the subtree please consider using RxMultiProvider as it improves readability and eliminates the need to nest multiple RxBlocProviders.
In our Counter sample, we simply wrap the home page with RxBlocProvider, which makes it accessible in the HomePage. However, if you are using any provider-based package such as auto_router in your project, you can benefit from wrapped_route, which wraps your route with a parent widget like a RxBlocProvider.
RxBlocBuilder
RxBlocBuilder is a Flutter widget that requires a RxBloc, a builder, and a state function. RxBlocBuilder handles building the widget in response to new states. RxBlocBuilder is very similar to StreamBuilder but has a more simple API to reduce the amount of boilerplate code needed.
The builder function should be a pure function that returns a widget in response to the state change, which will potentially be called many times.
The state function determines which exact state of the BloC will be used.
If the BloC parameter is omitted, RxBlocBuilder will automatically perform a lookup using RxBlocProvider and the current BuildContext.
Let’s now see how we can access the count state from the HomePage
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) =>
Scaffold(
...
RxBlocBuilder<CounterBlocType, int>(
state: (bloc) => bloc.states.count,
builder: (context, snapshot, bloc) =>
snapshot.hasData ?
Text(snapshot.data.toString()):
Container()
)
}
In case your state is of the Result type, please consider using RxResultBuilder, which is similar to RxBlocBuilder, but is designed to handle the Result state in an easier way. It provides callbacks such as buildSuccess, buildError, and buildLoading.
RxBlocListener
RxBlocListener is a Flutter widget that takes a RxBlocWidgetListener and invokes it in response to a state change in the BloC. It should be used for functionalities that need to occur once per state change such as navigation, showing a SnackBar, showing a Dialog, etc…
If the BloC parameter is omitted, RxBlocListener will automatically perform a lookup using RxBlocProvider and the current BuildContext.
Let’s see how we can react to the errors from the BloC and show the SnackBar accordingly.
RxBlocListener<CounterBlocType, String>(
state: (bloc) => bloc.states.errors,
listener: (context, errorMessage) =>
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(errorMessage),
),
)
Conclusion
flutter_rx_bloc provides you with a sufficient widget library that takes care of the lifecycle of your reactive BloCs. Since it’s based on the provider package it’s compatible with many great libraries such as auto_route and many more.