Flutter development series – Part 5 – BLoC pattern and navigation in Flutter

After a good while without posting anything to this Blog. I’m back.

Welcome to part 5 of the Flutter development series. In this post, we will be exploring the BLoC pattern applied to navigation in Flutter.

In the last post of the series, we learned how to use the BloC pattern in Flutter to manage the state and handle the business logic of our app. Now let’s use BLoC to handle the navigation to different screens of the application.

What is the BLoC pattern?

For a better absorption of the content of this post, one should have a clear understanding of the BloC pattern and how it works. If you haven’t, please refer to my previous post: BloC pattern in Flutter for a walkthrough.

Adding the BLoC library to your project

As usual, let’s start adding the dependency to the project. Edit the pubspec.yaml file:

And install it:

$ flutter pub get

Loyalty App navigation architecture

Before we move to the implementation, let’s break our navigation into different layers so we can visualize how it works:

Image with arch.

  • Presentation layer: Responsible for the UI of the application. If you want to navigate no another screen upon a click of a button for instance. The screen will send an event to the NavigationBloc.
  • Domain layer: This is where the navigation logic is contained.
  • Navigator layer: The layer responsible for containing the actual call for opening new screens or to pop existing ones from the stack.

Implementing the BLoC navigator

Create a new class and name it navigator_bloc.dart. This class will contain the logic to navigate to different screens based on Events.

Events and States in BLoC

bloc-architecture
BLoC architecture diagram.

Quick recap from the previous post.

Every time we want to change the state of our application, we start by emitting an event. Consequently, The function mapEventToState will be called, handle the event and return a state accordingly.

Implementing the BLoC States and Events

As you can see, our navigator_bloc.dart needs the NavigatorEvent type. Let’s implement it.

Create a new file and call it navigator_event.dart:

NavigatorEventPop will be emitted every time we want to pop a screen or in other words, navigate back.

The NavigatorEventAdd on the other hand will actually navigate to a new page, in this case called LoyaltyAddPage.

Testing

Because we test.

Taking care of the back stack

By default, when we navigate back, Flutter actually takes care of popping the current screen and showing the previous one.

Note that, if we let Flutter do that, the state of our navigator will be incorrect in the NavigatorBloc.

Wrong state

State diagram – wrong state

Note that after we clicked on the add button on top of the first screen, we emitted an event: NavigatorEventAdd. The AddPage was then shown, and the state was changed to Add page state. So far so good.

Things start to go wrong when we click the back arrow located on the top left on the second screen. Same would happen if we tapped the Android OS back button.

The previous screen will be shown, but the state on our NavigatorBloc would be wrong, it would still be AddPageState, since we didn’t use our navigator but let Flutter take care of it.

How to solve it

There is not much to it. Solving it, is done simply using the NavigatorBloc every time we need to navigate in our application, even when navigating back.

State diagram – correct state

In order to do that, we need to override the pop functionality in each and every screen we are expecting to navigate back.

To override the pop behaviour we will need to wrap the screen with the WillPopScope widget.

WillPopScope widget

The WillPopScope widget will register a callback every time the user tries to navigate back.

In our case, the only screen we need to do it is the middle screen in the diagram, the AddPage.

Add the widget to the root of the page:

Conclusion

The goal of this post was to show we can use the Bloc Pattern to keep the navigation state of our application.

Some of the advantages of having Bloc managing the navigation state are:

  • The current state can be fetched at any time.
  • The routes can be conditionally evaluated based on the current state and the events.

Thank you for your time and I hope you learned enough of the BLoC pattern applied to navigation in Flutter to be able to use it in your future projects.


0 Comments

Leave a comment