Page-Switcher-View pattern

Alejandro Ferrero
Flutter España
4 min readOct 6, 2022

--

Have you ever had to show a different view on your Flutter App depending on whether some data was loading? Or if something failed? How about when the data was successfully retrieved? If this situation sounds familiar, that’s because it’s one of the most common and fundamental scenarios App developers deal with when implementing new screens on their Applications.

In this blog post, I present you with an approach to tackling this situation consistently and systematically. We’ll first review the ever-useful Page-View pattern with BLoC. Additionally, we’ll see how to improve it to address view-content switching based on asynchronous data status. Lastly, there’s a bonus section showing how to automate this pattern implementation process via the page_switcher_view brick.

What’s the Page-View pattern?

If you use BLoC with its flutter implementation, flutter_bloc, you’ve probably come across the following error:

ProviderNotFoundException (Error: Could not find the correct Provider<YourBloc> above this YourView Widget

As the error message further explains, this happens because you used a `BuildContext` that does not include the provider of your choice. There are a few common scenarios.

It is a typical problem that, in simpler words, means that you’ve tried to access a bloc within a Widget whose context does not have access to the said bloc. Thus, the Page-View pattern enforces the injection (provision) of any given blocs right above the widget(s) that may be consuming these blocs. In a more technical sense, this pattern guarantees that all blocs are injected at the precise depth within the WidgetTree so that any child Widgets may access them through the BuildContext object.

Moreover, this pattern also facilitates Widget testing by allowing to mock the injected bloc and enabling developers to focus solely on widgets. For further context into this topic, check my colleague Marcos Sevilla’s article, Cleaner Flutter Vol. 10: State and UI.

See the example below about how to implement this pattern.

MyPage.dart

For more information on how to access a bloc instance via the BuildContext object refer to the flutter_bloc library docs.

Page-Switcher-View

Having discussed the general case for the Page-View pattern, we can now focus on a specific yet frequent scenario: switching the view content based on async data status.

State Management

For that, let’s first take a look at MyState.

MyState.dart

Notice how we use the MyStatus enum and the copyWith method to handle MyBloc’s state through a single, non-abstract class. MyStatus will represent the current status of the async data stored in MyState under the myAsyncData variable. Additionally, the copyWith method allows changing the bloc’s state by creating a new instance of MyState with updated data while keeping it immutable.

If we now look at MyBloc, we’re emitting new states based on the current status of the asynchronous execution when handling the MyDataRequested event.

MyBloc.dart

It’s worth noting that we emit a new state with an updated MyStatus value at every step of the asynchronous execution:

  • Before we execute the asyncCall, we emit a state including MyStatus.loading to signify an asynchronous operation is being performed.
  • If asyncCall completes successfully, we emit a state including MyStatus.success and the retrieved data to signify the asynchronous operation completed as expected.
  • If asyncCall fails to complete, we emit a new state including MyStatus.error to signify that something went wrong while executing the asynchronous operation.

UI

Let us now introduce the UI implementation of this pattern. The main difference to the general Page-View pattern approach is the introduction of a middleman or handler widget, which we will call Switcher.

If we look at MyPage, we see that we’re adding the MyDataRequested event as soon as MyBloc is instantiated and injected. Moreover, the child is now MySwitcher, instead of the previous MyView widget shown in the Page-View pattern explanation.

MyPage.dart with Switcher

But… what’s a Switcher?

In this context, a Switcher is just a not-so-fancy way of referring to a Widget whose sole purpose is to determine which view content to show based on a given BlocState’s status. Let’s check out the example below before we dive into the details.

MySwitcher.dart

All we’re doing is

  • Listen to changes on the MyState’s status property via a bloc selector.
  • Use a switch-case statement based on this changing value to determine which content to show in the UI.

Keep in mind that the status property must be an enum so that we’re handling all the possible values exhaustively when creating the switch statement. Hence, this approach forces developers to cover all the potential scenarios defined as values for the status enum property. For instance, we’re using a simple CircularProgressIndicator to tell the user something is still loading, but we could create a fully-fleshed view with shimmering effects or any other content/effects — the same goes for the error case. Lastly, the good ol’ View piece of the Page-View pattern is still present and will be accessed via the success case.

Could we automate this?

Yes, we can. Since this approach is both systematic and consistent, we can use mason to create any app features that leverage this pattern. All you need to do is use the page_switcher_view brick, which will populate all the necessary directory structure and boilerplate so you can focus on the actual feature’s implementation.

And that is it! I would love to hear your feedback about this blog or discuss any related topics, so feel free to drop a comment or reach out to me on Twitter.

--

--

Alejandro Ferrero
Flutter España

🤤 Founder of Foodium 💙 Lead Mobile Developer at iVisa 💻 Former Google DSC Lead at PoliMi 🔗 Blockchain enthusiast 🇪🇸 🇺🇸 🇮🇹 🇦🇩 Been there, done that