CodeX
Published in

CodeX

CODEX

Flutter Navigator 2.0 for Authentication and Bootstrapping — Part 4: Bootstrapping

In the third part of this series, we explored the Navigator 2.0 API with the authentication use case. In this article, we handle the bootstrapping process and build the navigation stack accordingly.

Let’s start with clarifying what I mean by bootstrapping. According to techterms.com website:

… bootstrapping is the startup process that takes place when you start up a computer… While bootstrapping is often associated with the system boot sequence, it can be used by individual applications as well. For example, a program may automatically run a series of commands when opened. These commands may process user settings, check for updates, and load dynamic libraries ... They are considered bootstrap processes because they run automatically as the program is starting up.

In many applications, when the app is launched, the authentication state is checked first. If the user is logged in, the app prepares itself by fetching user data from the local and remote data sources. Usually, a splash screen is shown to a user until the app is ready. In this article, we focus on the navigation of screens starting from the launch of the app until the point that the app is showing the home screen with user-specific data.

ColorsRepository

In the previous samples, the list of colors is accessed from Flutter's Colors class immediately. In this sample, we access the colors from the ColorsRepository class asynchronously during the bootstrapping process. The fetchColors() method returns the same color list from the Colors class with a delay of 3 seconds.

Normally, the repository pattern is used for abstracting the data access. Thus, we shouldn’t implement the data access logic here. However, in our case, we implemented the data access logic in the repository classes for easy explanation with less code and staying more focused on the actual topic.

The App

When the app is launched, the Router widget is instantiated and located at the top of the app widget tree as in the previous samples. In this sample, we inject the ColorsRepository together with the AuthRepository to the app through ColorsViewModel and AutViewModel classes using the Provider State Management pattern.

The RouterDelegate

The list of colors state is saved in the _colors property of the RouterDelegate class together with the _loggedIn , _selectedColorCode and the _selectedShape states.

Let’s see what happens when the RouterDelegate class is initialized:

  • The RouterDelegate asks to the AuthRepository the authentication state, and waits until it receives the result.
  • Meanwhile, the Router widget calls the build method of the RouterDelegate and SplashScreen for fetching the checking login state is shown to the user as explained in the previous article.
  • When the authentication state is received, the RouterDelegate notifies the Router widget inside the setter method of the _loggedIn.
  • The Router widget asks the RouterDelegate to build the navigation stack accordingly.

If the user is already logged in

  • Navigator widget with _splashStack is returned from the build method of the RouterDelegate and SplashScreen for fetching the colors is shown to the user.
  • The RouterDelegate requests the colors from the ColorsRepository class. It calls ColorsRepository.fetchColors() method, and waits until it receives the colors.
  • When the color list is fetched, the RouterDelegate sets the colors state and notifies the Router widget inside its setter method.
  • The Router widget asks the RouterDelegate to build the _loggedInStack navigation stack.

If the user is not logged in

  • Navigator widget with _loggedOutStack is returned from the build method and LoginScreen is shown to the user.
  • When onLogin callback is invoked inside the LoginScreen, loggedIn state is set to true and the Router widget is notified.
  • Navigator widget with _splashStack is returned from the build method of the RouterDelegate and SplashScreen for fetching the colors is shown to the user.
  • ColorsRepository.fetchColors() method is invoked.
  • When the color list is fetched, the RouterDelegate sets the colors state and notifies the Router widget inside its setter method.
  • The Router widget asks the RouterDelegate to build _loggedInStack the navigation stack.

Different from the previous sample app, the _splashStack is built also considering the _colors state. If the _colors has not yet been fetched and the user is logged in, the app should show the SplashScreen because it is waiting for the colors from the ColorsRepository. The _loggedInStack and the _loggedOutStack is exactly the same as the second sample.

In this sample app, we associate the list of colors with the user. Therefore, when the user logs out, we clear the states by setting _colors , _selectedColorCode and the _selectedShape states to null. We also should call the ColorsRepository.clearColors() method to clear the data associated with the user.

ColorsViewModel

The ColorsViewModel and AuthViewModel classes extend ChangeNotifier mixin and they are injected into the app tree widget using the Provider state management library. The ViewModel classes are used to represent the states of the data fetching process. It is debatable for many developers whether state management with Provider pattern is exactly MVVM (Model-View-ViewModel). I am not going to explain my opinions on this to give the focus more on the the navigation topic.

loggingIn , loggingOut , fetchingColors , and clearingColors states inside the view models are accessed by the child widgets to figure out if an operation is started, in progress, and done.

Logout Fab

When the LogoutFab widget is pressed:

  • AuthViewModel.logout is called. This method sets the logingOut state inside the AuthViewModel to true, and calls notifyListeners which will cause a rebuild of the LogoutFab .
  • LogoutFab widget shows a floating action button (fab) with a CircularProgresIndicator
  • When the logout process is done, logingOut state inside the AuthViewModel is set to false and the LogoutFab widget is notified.
  • This time, the rebuilding of the LogoutFab widget will not be noticeable because the subsequent colorsViewModel.clearColors() call will set the clearingColors state to true which causes another rebuilding.
  • LogoutFab will be rebuilt, and a FAB with a CircularProgresIndicator is shown again.
  • When the clearColors() process is done, clearingColors state inside the AuthViewModel is set to false and the LogoutFab widget is notified.
  • Again, the rebuilding will not be noticeable because the subsequent onLogoutcall will cause a rebuilding of the navigation history inside the RouterDelegate and as a result, LoginScreen will be shown.

HomeScreen, ColorScreen, ShapeScreen

We want the HomeScreen , ColorScreen , and ShapeScreen to have the same logic so that whenever the LogoutFab is pressed, the user will be notified with a text telling that logout is in progress and clearing the color list.

The state management inside these widgets is straightforward. If either AUthViewModel.logingOut or ColorsViewModel.clearingColors are true, we show the InProgressMessage which is a custom widget that shows the operation name and the screen name to the user.

Disclaimer

Note that in this sample app, all the properties used to determine the current app state are stored separately in the RouterDelegate class for demonstration purposes and easier explanation. This is not recommended as the number of these properties is subject to increase over time during application development, and it will be overkill to store them all. We need to apply best practices with a clean architecture. For example, we don’t need to store the colors list inside RouterDelegate. In fact, we shouldn’t inject the repository classes to the RouterDelegate because RouterDelegate class doesn’t need to know which repositories are needed to find out the app state. Instead, we could inject the use case classes that interact with the repositories using dependency injection libraries. Although clean architecture is out of this series of article’s scope, I would strongly recommend further reading if the reader is not familiar with the topic.

Conclusion

In this article, we learned how to build a navigation stack in response to the app state changes caused by bootstrapping. You can find the source code on the Github page. The project includes multiple main.dart files. The easiest way of running this sample app is right-clicking on the main_002_03.dart file and selecting the Run 'main_002_03.dart'.

Until now, we used the Navigator 2.0 API for mobile applications. All these samples will also work for Web applications but the user experience will be poor since the Web browser’s address bar won’t be updated with the navigation stack updates. In the next article, we will learn how to parse and restore Web URL links and navigate accordingly.

Special thanks to Jon Imanol Durán who reviewed all the articles in this series and gave me useful feedback. If you liked this article, please press the clap button, and star the Github repository.

--

--

--

Everything connected with Tech & Code. Follow to join our 900K+ monthly readers

Recommended from Medium

Easy and maintainable test data — The Kotlin way

Are you an iOS developer? Spigot, Inc. needs you!

Applying Netflix DevOps Patterns to Windows

Flow chart showing how Docker image inheretance is used in the creation of a Windows AMI.

Python Programming Online for Beginners

Virtual Environments for Python

How a Writer is Like a Tree: A Metaphor for Creativity

Achieving the Atlantis Workflow with Spacelift

Archive Link: VIM Usage

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
Cagatay Ulusoy

Cagatay Ulusoy

Flutter and Android Mobile App Developer

More from Medium

Using GraphQL in Flutter Apps

Migrating your Flutter project to null safety

Nusafety errors

How to use Flutter Time Series Charts with Firebase

Flutter101: [part-1] A fast-fowarded guide to develop flutter apps for senior (impatient)…