Blocs with Reactive Repository
Inspired by the updated section on “(Avoiding) Bloc-to-Bloc communication” at https://bloclibrary.dev/#/architecture?id=bloc-to-bloc-communication, we’ll explore a use case where “reactive repository” solution is very elegant, if not the only one that covers all cases.
You can find the entire application code at https://github.com/slovnicki/reactive_repositories
Here’s a diagram of what we want to accomplish, so let’s start with why do we want to accomplish that :)
The problem
Consider an application where we have a screen with a list of items that are sorted based on some property a user can toggle, but the toggling is done inside another route (a screen, dialog or bottom sheet) and should rebuild the route below to reflect the updated item and ordering of the list.
Architecture
- 2 main Widgets:
ListScreen
andDetailsModal
which are shown on separate routes - 2 Cubits: one that rebuilds the
ListScreen
and one that rebuilds theDetailsModal
- 1 Repository which both Cubits can use to fetch and update items
Intended behavior
When we click on “Toggle favorite” for Burrito, we would like to trigger a rebuild of ListScreen
to show the updated list of items where Burrito is appropriately placed further up than it was before, because we sort items by the isFavorite
property we’re toggling.
Approaches
It would seem we need to trigger the ListCubit
from successful toggle action on DetailsCubit
. The mentioned section on Bloc-to-Bloc communication (https://bloclibrary.dev/#/architecture?id=bloc-to-bloc-communication) tells us that we should handle this either
- by using
BlocListener
to listen for success state onDetailsCubit
and then triggeringListCubit
explicitly - by having our
ListCubit
listen to aStream
fromItemsRepository
which adds new values to the stream after each successful toggling
First approach can get a bit tricky when we’re dealing with different routes that don’t share context
and if we’re using declarative navigation and/or deep-linking where it’s not straightforward to provide both routes with the same instance of ListCubit
(if we don’t want it above entire app).
We’re now going to explore the second solution — “reactive repository”.
The solution
Let’s look at the diagram again
Cubit
The basic idea is for ListCubit
, instead of depending on someone explicitly calling loadItems
on it, to emit new states (thus rebuilding the ListScreen
) whenever the ItemsRepository
adds a new list of items to the stream. We can achieve that by having our ListCubit
subscribe to the stream.
Repository
In our abstract repository, we’re exposing a Stream
called items
, the one that the ListCubit
is subscribing to in the above snippet.
We’re exposing a broadcast stream because repository doesn’t know how many subscribers will it have and should generally support many.
Now in the implementation (FakeItemsRepository
for this example), we are adding new lists of items to the stream on two occasions, but the second one is of more interest to us in this article.
- On initial fetch
- Every time an item is successfully toggled
The code
You can find the entire application code at https://github.com/slovnicki/reactive_repositories. Feel free to create PRs, issues or contact me on Twitter for any further discussions: https://twitter.com/slovnicki
Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm