Taking the right route with Flutter.

Tair Rzayev
Apr 2, 2020 · 4 min read
Image courtesy https://unsplash.com/photos/6gP_a7WP0mM

There is a lot of good documentation and articles about the navigation, firebase dynamic links, and state management in Flutter. While all of them are clear and understandable in isolation, many developers may find themselves struggling to “put it all together” in the real-world application.

One of the problems with deep linking examples is that it’s not always as straightforward as pushing a specific route with the parameters, extracted from the deep link. For example, the deep link might only be available for users, who are logged in, in which case the user has to go through the login flow before opening the deeply linked widget.

I am sure a lot of you have noticed this by tapping on the link for some app, passing the login process only to realize the app has lost track of the link you have tapped and landed you on the home screen, making you tap the link again.

The problem

Route user to the specific screen in the app after they tap the app deep link. If any higher-priority steps such as authentication require taking care of — perform them, keeping in mind that the deep link has to be opened eventually.

Our toolbox

NB: It is assumed the reader is familiar with Flutter state management & specifically with the BLoC library. If you are not yet — I encourage you to do so- it’s really good stuff!

Let’s get to the code.

If you can’t wait to see what we end up with, here is the complete project.

If you want to go through this step-by-step in more detail, let’s get started!

Creating the app launcher.

Our app will always begin its life from the app launcher widget (a MaterialApp), which will push the required root widget, depending on the current app state. The flow we will be trying to achieve is this:

In real-world apps there might be extra onboarding steps aside from the login (accepting T&Cs, setting the username or photo, completing the onboarding tutorial) but we will stick just to the login flow to keep our example simple but keeping in mind that is has to be extendable for other use cases.

We will first define AppRoute class, which will represent possible routes the app can take (in our case either the home route or the details screen):

Define the set of possible launch states, the app can be in:

We will also define AuthRepository. Authentication details are likely to differ from app to app and are not relevant to this article so let’s only focus on its interface:

Let’s now build an AppLaunchBloc :

This BLoC will either accept CheckLoginStatus event, which will set the optional deep link and refresh the launch state or RefreshLoginStatus event, which will simply refresh the launch state. It is also important to note that we are keeping our deep link around in AppLaunchState.deepLin field until we end up in the state, in which we can open it (which is AuthenticatedState for this app).

What we need now is the actual UI widget, which will submit these events to the AppLaunchBloc and react to its state changes by pushing the required widget, which brings us to the AppLauncher:

That snippet interspersed with a few comments, which hopefully make it more clear.

So far so good, we now have an AppLauncher widget, which pushes the required route, depending on the state, emitted by the AppLaunchBloc.

If user is not authenticated, AuthPage widget is pushed, which looks like this:

Its BLoC is omitted as it’s not relevant to the point we are about to discuss. What’s important is that after user signs in, we effectively remove any widgets until the root and then open the launcher after user signs in:

Basically, we are going back to AppLauncher , asking it to refresh the app state (which will now be logged in), which will make UI open the appropriate widget (either HomePage or DetailsPage for the deep link).

One could argue that we could launch the HomePage directly from the AuthPage . We might as well pass the deep link to the AuthPage and handle it there too. This is certainly an option but brings a couple of problems:

  • The routing responsibility will be “smeared” across multiple widgets ( AppLauncher and AuthPage ), which is harder to keep track of and maintain.

Conclusion

First of all, congratulations on getting that far into this article!

We have discussed one of the ways to handle the app deep links, making sure it persists through the login flow or potentially any other flow the user may have to go through on the first app launch. I encourage you to clone and play with the complete source of the sample app for this article

This is definitely not the only way to handle this so if you have a better idea or found a bug/issue in the article or the code — please, put that down in the comment :).

Chili Labs

Fascinating journey of a mobile development company from…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store