Simple Recipes App made in Flutter — Firebase and Google Sign-In

Michal Krol
Flutter Community
Published in
6 min readNov 13, 2018

--

Firebase, Google Authentication and Flutter. Let’s see how it works.

Firebase includes a lot of great tools for building, maintaining and improving quality of apps. Let’s have a more detailed look at Google Sign-In and how to integrate this functionality into a Flutter project.

This series of articles describes the implementation of a simple recipes app made in Flutter. In previous articles Simple Recipes App made in Flutter — Introduction and Simple Recipes App made in Flutter — List View we’ve learned how to implement the user interface.

You can find the code used in this and previous articles in the recipes_app repository on github. If you have already read previous articles of this series, we’re ready to go.

Photo by Jairph on Unsplash

Setup

First, we have to create a new Firebase project and add our app to it. I can only recommend you to follow this guide written by Google.

To implement the Google Sign-In functionality we are going to use packages firebase_auth and google_sign_in as libraries. Add the lines that follow to the dependencies section in pubspec.yaml.

pubspec.yaml

To get the packages execute flutter packages get on the command line.

Now, we can move on to the implementation.

Implementation

Before we start with the implementation we have to choose the pattern for the state management in our app. There are many ways to reach this goal. We’re going to manage the state in the Flutter way of doing it.

Do you remember how we’ve implemented the list view? We’ve created an active parent widget that gets notified by its inactive widgets in order to update the content as soon as the list of favorites changes. The pattern that we are about to implement today is pretty similar. In the implementation we’re going to use the class InheritedWidget.

InheritedWidget ?

Basically, we can describe InheritedWidget as a parent widget which passes its data down the widget tree. You can access the data from every widget in the app by using the method inheritFromWidgetOfExactType of the BuildContext class.

In previous articles we’ve learned how to access the theme from every widget in the widget tree. We’ve used Theme.of(context) to get styles of the theme and apply them to our widgets.

Here, we are going to do the same. We’re going to access data of the state by StateWidget.of(context). The class StateWidget is going to wrap a custom InheritedWidget. Furthermore, it is going to provide the of method and do some additional work on the initialization of the state.

Let’s start with the implementation step by step.

Model

We are going to store the state of our app as an object of the class StateModel. The state is going to provide the information about the current signed-in Firebase user. In addition, it is going to say us whether our app is loading.

In order to implement the StateModel class create a new file state.dart in the model directory.

Here’s the implementation:

lib/model/state.dart

Helper Methods

We are going to put the code below in a new file auth.dart in the utils directory. In the next step of the implementation we’re going to use these helper methods to authenticate the user with Google.

You will find that we are using keywords async and await in multiple lines of the code that follows. Why do we need async and await?

Dart provides us the async keyword for writing an asynchronous code. We can use this keyword if we want to write methods which are going to run in the background while the rest of the code is being executed at the same time. But how about using async in combination with the await keyword?

Let’s see what the official Dart documentation says about it:

Note: Although an async function might perform time-consuming operations, it doesn’t wait for those operations. Instead, the async function executes only until it encounters its first await expression (details). Then it returns a Future object, resuming execution only after the await expression completes.

Don’t hesitate to experiment with the asynchronous programming in Dart. You can find more about this topic in A Tour of the Dart Language written by the Dart team.

Here’s the implementation of our helper methods:

lib/utils/auth.dart

Cheers! We’re ready to move on.

The State Widget

Let’s take a look at the implementation of our state widget.

We’re going to be able to access the state included into our custom InheritedWidget from everywhere in the widget tree by using the public class StateWidget. It is going to implement the of method. The class _StateDataWidget that inherits from InheritedWidgetis going to be private and store only the state data in its member of the type _StateWidgetState.

In this way we are going to encapsulate the way of how we provide access to the state and how we store its data. But what about the logic of the initialization of the state including the usage of our helper methods defined in the last step? This job is going to be done by the class _StateWidgetState.

Put the code below into a new file called state_widget.dart in the lib directory.

lib/state_widget.dart

Now, let’s use StateWidget and change the code in main.dart:

lib/main.dart

Great! After this change the app’s state is going to be initialized on every start of the app. As a next step, we are going to change the implementation of our app so that it depends on the state.

Home Screen

Until now the route of the login screen has been the initial route of our app. Since we are able to access the state it’s obsolete. If a user is signed-in, we want to put only the HomeScreen widget into the widget tree. In the next step we are going to change the initial route to the route of the home screen.

Since the property initialRoute of MaterialApp overrides the default route / we do not need to use initialRoute anymore. Just delete the line in app.dart where initialRoute is being set. Our app is going to start with the HomeScreen widget on the next run.

lib/app.dart

In HomeScreen we are going to:

  • Show a loading indicator if the app is loading
  • Show the login screen if there is neither a currently signed-in user nor a previously signed-in user
  • Show recipes if a user is signed-in

The code that follows contains new private methods which are being used to implement the scenario described above and build the content based on the app’s state.

lib/ui/screens/home.dart

Awesome! If you run the app, it’s going to show the login screen because we have not used Firebase and there is no previously signed-in user. We have successfully implemented Google authorization and state management for our app.

To finalize the implementation for today we still need to make a little change in the class _LoginScreenState.

Login Screen

The widget GoogleSignInButton in the build method of _LoginScreenState just navigates to the home screen by now. Let’s change it and use the method signInWithGoogle of StateWidget:

lib/ui/screens/login.dart

Conclusion

Today we have learned a lot about Flutter.

Let me summarize the topics:

Firebase is a very nice tool for deploying serverless mobile applications. In the next article we’re going to focus closely on Firestore. We’re going to work with real data and store users’ favorites in a cloud database in Firestore.

Thanks a lot for reading. I wish you happy fluttering.

--

--

Michal Krol
Flutter Community

👨🏼‍🏭📱 freelance fullstack mobile and web apps developer | 💙 Flutter enthusiast | https://krolmic.dev/