Simple Login Flow With Flutter and Firebase

Simple Login Flow With Flutter and  Firebase

Simple Login Flow With Flutter and Firebase .In this article we implement a simple authentication flow in Flutter, in less than 100 lines of code. After creating a new Flutter project

In this piece, we will create a simple application with the following components:

  • Default Main App Entry Point
  • Use of FutureBuilder Widget to wait for data before rendering UI, the concept used throughout the app
  • Login Page
  • Home Page
  • Authentication Service
  • Demonstrate the use of the Provider as discussed in the Flutter Documentation Simple App State Management

There are plenty of examples online about setting up Firebase for Flutter so I will jump right into the code instead of walking thru the basics.

See Google CodeLabs Flutter for Firebase for step-by-step instructions for setting up you project on iOS or Android

Create a Test User in Firebase

Since we are just building the application and there is no functionality to create users right now, log in to you Firebase Console and add a user to your project. Be sure to enable email authentication when updating the project in your Firebase Console.

Cleaning Up the Default Flutter Project

First, let's create the project:

flutter create simple_firebase_auth

Now let's do some project cleanup, open up the project and delete the existing HomePage and HomePageState widget from the file main.dart.

Change the home property of the MaterialApp widget to point to the LoginPage widget we are about to create in the next section.

The file should look similar to this when completed:

import 'package:flutter/material.dart';
import 'package:simple_firebase_auth/login_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}

Markdium-javascript.js

Create the Login Page Widget

Let's walk through the creation of the LoginPage for the application. We need to capture an email and a password to pass to the AuthService to call the login function.

We are going to create a simple page with the required TextFormField widgets and one RaisedButton that will log a user in when clicked.

  1. Open your editor and create a new file in the lib directory named login_page.dart
  2. Paste the contents below into the file login_page.dart
import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Login Page Flutter Firebase"),
      ),
      body: Center(
        child: Text('Login Page Flutter Firebase  Content'),
      ),
    );
  }
}

Markdium-javascript.js

You should be able to run the code to see what the screen looks like now. Be sure to change the default route or home property in main.dart widget to LoginPage while we work through the UI so you can see the changes update live.

Style and Adding Text Fields

Let's make the body of the page a centered Column with the children of the column being primarily the TextFormField and the RaisedButton.

The centered container to hold the form fields and buttons:

 body: Container(
      padding: EdgeInsets.all(20.0),
      child: Column()
    )

Markdium-javascript.js

Next, add the actual form field widgets and the buttons as children of the Column widget. We will do some basic styling of the form fields so that this looks presentable. See the Flutter documentation for more information on TextFormFields.

 body: Container(
    padding: EdgeInsets.all(20.0),
    child: Column(
      children: <Widget>[
        Text(
          'Login Information',
          style: TextStyle(fontSize: 20),
        ),
        TextFormField(
            keyboardType: TextInputType.emailAddress,
            decoration: InputDecoration(labelText: "Email Address")),
        TextFormField(
            obscureText: true,
            decoration: InputDecoration(labelText: "Password")),
        RaisedButton(child: Text("LOGIN"), onPressed: () {}),
      ],
    ),
  ),

Markdium-javascript.js

Let’s add some spacing between the fields in the column so it is more presentable. We are going to use the SizedBox widget and set the height property to get some spacing in the application. Replace the children property of the Column widget to get the desired spacing.

children: <Widget>[
    SizedBox(height: 20.0),    // <= NEW
    Text(
      'Login Information',
      style: TextStyle(fontSize: 20),
    ),
    SizedBox(height: 20.0),   // <= NEW
    TextFormField(
        keyboardType: TextInputType.emailAddress,
        decoration: InputDecoration(labelText: "Email Address")),
    TextFormField(
        obscureText: true,
        decoration: InputDecoration(labelText: "Password")),
    SizedBox(height: 20.0),  // <= NEW
    RaisedButton(child: Text("LOGIN"), onPressed: () {}),
  ],

Markdium-javascript.js

Getting Text Values from Form Fields

We are going to be using a Form widget and a GlobalKey, additional information on these concepts can be found in the flutter cookbook section Building a form with validation.

Add the formKey in the LoginPage widget:

class _LoginPageState extends State<LoginPage> {
  final _formKey = GlobalKey<FormState>();

Markdium-javascript.js

Then add two new fields to hold the email address and password values we will need to send to Firebase for authentication:

class _LoginPageState extends State<LoginPage> {
  final _formKey = GlobalKey<FormState>();
  String _password;
  String _email;

Markdium-javascript.js

Next, add a property onSaved to the TextFormFields we have for email and password. When the save method is called on the form, all of the widgets onSaved methods will be called to update the local variables.

TextFormField(
      onSaved: (value) => _email = value,    // <= NEW
      keyboardType: TextInputType.emailAddress,
      decoration: InputDecoration(labelText: "Email Address")),
  TextFormField(
      onSaved: (value) => _password = value, // <= NEW
      obscureText: true,
      decoration: InputDecoration(labelText: "Password")),

Markdium-javascript.js

Wrap the Column widget with a new Form widget, the code should look similar to this:

body: Container(
        padding: EdgeInsets.all(20.0),
        child: Form(          // <= NEW
          key: _formKey,      // <= NEW
          child: Column(
            children: <Widget>[
            ....
            ],
          ),
        ),
      ),      

Markdium-javascript.js

Now that the fields are set and the TextFormField are updated, we can use the _formKey to not only validate the fields provided but also retrieve the values locally by calling the save method.

Replace the code in the RaisedButton onPressed method to the following, and you will see that we are getting the values for email and password set in out widget. We can now pass these values to the AuthService that wraps the Firebase sign-in functionality.

 // save the fields..
    final form = _formKey.currentState;
    form.save();

    // Validate will return true if is valid, or false if invalid.
    if (form.validate()) {
      print("$_email $_password");
    }

Markdium-javascript.js

Create the Home Page Widget

For now, we will keep the home page simple, since our goal is to demonstrate how the flow works. Ignore the commented out LogoutButton widget, we will discuss that in a later section of the tutorial.

  1. Open your editor and create a new file in the lib directory named home_page.dart
  2. Paste the contents below into the file home_page.dart
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      appBar: AppBar(
        title: Text("Home Flutter Firebase"),
        //actions: <Widget>[LogoutButton()],
      ),
      body: Center(
        child: Text('Home Page Flutter Firebase  Content'),
      ),
    );
  }
}

Markdium-javascript.js

  1. Open main.dart and add the following import statement
import 'home_page.dart';

Markdium-javascript.js

  1. To verify that the page is working properly, change the home property from this:
home: HomePage(title: 'Flutter Demo Home Page'),

Markdium-javascript.js

To this:

home: HomePage(),

Markdium-javascript.js

Creating a Template for an Authentication Service

Here we will build out the authentication service separate from Firebase, validate that everything works and then integrate Firebase.

In this service, we are using a mixin called ChangeNotifier and a method notifyListeners which will allow for the widgets that are using this Service to be updated when the method is called. We are calling notifyListeners when we update the currentUser property because that means that the user has either logged in or logged out and we want the application to update based on the user's state.

More information on Provider and State Management can be found here in the Flutter Documentation

What we need as a baseline is the following:

import 'dart:async';
import 'package:flutter/material.dart';

class AuthService with ChangeNotifier {
  var currentUser;

  AuthService() {
    print("new AuthService");
  }

  Future getUser() {
    return Future.value(currentUser);
  }

  // wrappinhg the firebase calls
  Future logout() {
    this.currentUser = null;
    notifyListeners();
    return Future.value(currentUser);
  }

  // wrapping the firebase calls
  Future createUser(
      {String firstName,
      String lastName,
      String email,
      String password}) async {}

  // logs in the user if password matches
  Future loginUser({String email, String password}) {
    if (password == 'password123') {
      this.currentUser = {'email': email};
      notifyListeners();
      return Future.value(currentUser);
    } else {
      this.currentUser = null;
      return Future.value(null);
    }
  }
}

Markdium-javascript.js

We will keep a local property in the service call currentUser which is the object storing the user when the user calls the login method and if the password matches we will set currentUser and the user will be logged in. This will now provide a user when the call is made to getUser method. For logging the user out, we will set the currentUser property to null indicating that we are no longer logged into the system.

Determining User State On Application Launch

The first challenge when working with the application is to determine which page to open when the application starts up. What we want to do here is determine if we have a user or not. We will be using an AuthService we created above combined with the FutureBuilder widget from Flutter to render the correct first page of either a HomePage or a LoginPage.

Using the Provider

In main.dart we will need to update the default main method to look like this; we are wrapping the whole application with the ChangeNotifierProvider to get the ability to scan up the widget tree and find an object of type AuthService.

void main() => runApp(
      ChangeNotifierProvider<AuthService>(
        child: MyApp(),
        builder: (BuildContext context) {
          return AuthService();
        },
      ),
    );

Markdium-javascript.js

Modifying the MyApp Widget

Go into the main.dart and make the following changes that will allow the MyApp widget to set the route. This widget will determine if the application should navigate to the HomePage widget or LoginPage widget when the app is launched.

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: FutureBuilder(
        // get the Provider, and call the getUser method
        future: Provider.of<AuthService>(context).getUser(),
        // wait for the future to resolve and render the appropriate
        // widget for HomePage or LoginPage
        builder: (context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return snapshot.hasData ? HomePage() : LoginPage();
          } else {
            return Container(color: Colors.white);
          }
        },
      ),
    );
  }
}

Markdium-javascript.js

Modifying the Login Page Widget

Now that the AuthService can be accessed using the Provider, we can call the login function when the used clicks the button. Open the file login_page.dart and find the onPressed method for the login button and make the following change

  // Validate will return true if is valid, or false if invalid.
    if (form.validate()) {
      var result = await Provider.of(context)
          .loginUser(email: _email, password: _password);
      if (result == null) {
        // see project in github for this code
        //return _buildShowErrorDialog(context,
        //    "Error Logging In With Those Credentials");
      }
    }

Markdium-Dart.dart

We are using the Provider.of method to look up the widget tree and get our AuthService and then we have access to all of the methods, specifically the loginUser method.

Conclusion

At this point, you should have a functioning application with the basic login flow where the user will be logged in successfully if you provide the password as password123.

I added in a little extra functionality of displaying an error message in a dialog box if some sort of error occurs.

Now we will integrate firebase into the application.

There are plenty of examples online about setting up Firebase for Flutter, so I will jump right into the code instead of walking through the basics. See Google CodeLabs Flutter for Firebase for step-by-step instructions for setting up your project on iOS or Android.

Create a Test User in Firebase

Since we are just building the application, and there is no functionality to create users in the application right now, please log in to your Firebase Console and add a user to your project. Please be sure to enable email authentication when updating the project in your Firebase Console.

Steps For Adding Firebase Functionality to the Project
  • Add the Firebase methods to the AuthService
  • Access the getUser property from the AuthService at startup to determine which page to load in main.dart
  • Modify HomePage to show email address of the logged in FirebaseUser
  • Modify LoginPage to call the loginUser method on the AuthService to login a user using the Firebase API to see if we can log in a real FirebaseUser
  • Finally, handle the errors appropriately when logging in and when looking for a current user at startup.
Authentication Service: Adding Firebase API Functionality

First the authentication service, which is where we are just wrapping some of the basic Firebase functions that we need for authentication and determining if there is already a user persisted from a previous session.

import 'package:firebase_auth/firebase_auth.dart';
import 'dart:async';

import 'package:flutter/cupertino.dart';

class AuthService with ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  ///
  /// return the Future with firebase user object FirebaseUser if one exists
  ///
  Future getUser() {
    return _auth.currentUser();
  }

  // wrapping the firebase calls
  Future logout() async {
    var result = FirebaseAuth.instance.signOut();
    notifyListeners();
    return result;
  }
  
  ///
  /// wrapping the firebase call to signInWithEmailAndPassword
  /// `email` String
  /// `password` String
  ///
  Future loginUser({String email, String password}) async {
    try {
      var result = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
      // since something changed, let's notify the listeners...
      notifyListeners();
      return result;
    }  catch (e) {
      // throw the Firebase AuthException that we caught
      throw new AuthException(e.code, e.message);
    }
  }
}

Markdium-Dart.dart

As you can see from the code above, we still have the same methods for accessing our AuthService; the only difference now is that we have replaced the call with real calls to the Firebase back end that you have set up.

Notice we no longer need to keep a property with the current user since Firebase will manage that for us. All we need to do is call the method getUser, and if there is a user we will get an object. Otherwise it will return null.

Most important to notice is that we are calling notifyListeners() when the login state is changing during logging in or logging out.

Modifying main.dart

There are no real modifications needed to the file since we are working with the same external API. The only difference is that now we are returning a FirebaseUser object, so let’s add a specific type to the code, and touch up a few more things.

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: FutureBuilder(
        future: Provider.of(context).getUser(),
        builder: (context, AsyncSnapshot snapshot) { //          ⇐ NEW
          if (snapshot.connectionState == ConnectionState.done) {
            // log error to console                                            ⇐ NEW
            if (snapshot.error != null) {
              print("error");
              return Text(snapshot.error.toString());
            }
            // redirect to the proper page, pass the user into the 
            // `HomePage` so we can display the user email in welcome msg     ⇐ NEW
            return snapshot.hasData ? HomePage(snapshot.data) : LoginPage();
          } else {
            // show loading indicator                                         ⇐ NEW
            return LoadingCircle();
          }
        },
      ),
    );
  }
}

Markdium-Dart.dart

We have added the object type, FirebaseUser, associated with the AsyncSnapshot, and we are now checking for an error in case there is a problem loading Firebase initially.

We have also added a new parameter to the constructor of the HomePage widget, which is the FirebaseUser object returned from getUser call made to the AuthService. We will see in the next section how the new parameter is used.

Finally, we added a new widget called LoadingCircle to give us a nice user experience when the application is starting up and accessing Firebase to check for a new user. See the code below for the LoadingCircle widget.

See documentation on CircularProgressIndicator

class LoadingCircle extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: CircularProgressIndicator(),
        alignment: Alignment(0.0, 0.0),
      ),
    );
  }
}

Markdium-Dart.dart

Modifying HomePage Widget in home_page.dart

We need to first modify the widget by adding a new constructor that will hold the Firebase user passed in from the FutureBuilder in main.dart

class HomePage extends StatefulWidget {
  final FirebaseUser currentUser;    // ⇐ NEW

  HomePage(this.currentUser);        // ⇐ NEW

  @override
  _HomePageState createState() => _HomePageState();
}

Markdium-Dart.dart

Now we have access to the information on the current user from the widget; we can access it when rendering the HomePage by make the modifications you see below. We will just add a few more widgets to the build method:

children: [
       SizedBox(height: 20.0),                         // ⇐ NEW
       Text(                                           // ⇐ NEW
         'Home Page Flutter Firebase  Content',
         style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
       ),
       SizedBox(height: 20.0),                         // ⇐ NEW
       Text(                                           // ⇐ NEW
          `Welcome ${widget.currentUser.email}`,
           style: TextStyle(    
              fontSize: 18,
              fontWeight: FontWeight.bold,
              fontStyle: FontStyle.italic),
        ),
       SizedBox(height: 20.0),
       RaisedButton(
           child: Text("LOGOUT"),
           onPressed: () async {
             await Provider.of(context).logout();
           })
     ],

Markdium-Dart.dart

Modifying LoginPage Widget in login_page.dart

Since the API signature hasn’t changed, we need to do very little to this function to get the desired results. However, it would be best to do some better error checking.

With Future we need to wrap the call with a try catch block since any errors that happen with Firebase will be thrown as exceptions. We then will display the error message in a dialog. See code for the method _buildErrorDialog and the rest of the changes below.

Add the new import for the error exception:

import  'package:firebase_auth/firebase_auth.dart';

Markdium-Dart.dart

Make the appropriate changes to the onPressed method of the login button.

onPressed: () async {
       // save the fields..
       final form = _formKey.currentState;
       form.save();

       // Validate will return true if is valid, or false if invalid.
       if (form.validate()) {
         try {
           FirebaseUser result =
               await Provider.of(context).loginUser(
                   email: _email, password: _password);
           print(result);  
         } on AuthException catch (error) {
           // handle the firebase specific error
           return _buildErrorDialog(context, error.message);
         } on Exception catch (error) {
           // gracefully handle anything else that might happen..        
           return _buildErrorDialog(context, error.toString());
         }
       }
     },

Markdium-Dart.dart

Add the code for the new private _buildErrorDialog method that will display errors from the call to the AuthService login method.

 Future _buildErrorDialog(BuildContext context, _message) {
    return showDialog(
      builder: (context) {
        return AlertDialog(
          title: Text('Error Message'),
          content: Text(_message),
          actions: [
            FlatButton(
                child: Text('Cancel'),
                onPressed: () {
                  Navigator.of(context).pop();
                })
          ],
        );
      },
      context: context,
    );
  }

Markdium-Dart.dart

Conclusion

At this point, you should have a functioning application with the basic login flow where the user will be logged into Firebase using the credential for the test user you added in the Firebase Console.

Try entering invalid credentials for the password, and incomplete email addresses, and the errors should be displayed appropriately.

Firebase Authentication in Flutter

Firebase Authentication in Flutter

Firebase Authentication in Flutter - Production Patterns. This tutorial will cover the implementation and architecture for Firebase Authentication. We use Firebase Authentication in production to keep my code maintainable and easy to manage. We cover the basic login and sign up functionality.

Today we'll be going over the production practices I follow when implementing email authentication using Firebase in Flutter. We'll be building a social media app called compound. It's called compound because that's the middle word of the book in front of me on my desk. "The Compound Effect". Even if you don't want to build a social media app, I'll be teaching you the principles you need to apply to a firebase project to build literally any app you want.

The Architecture

If you don't know, I use an Mvvm Style architecture with Provider for my UI / Business logic separation and get_it as a service locator. I've found this to be the most consistent and easy to understand architecture that I've used in production. It keeps implementations short and specific. In short the architecture specifies that each view or basic widget can have it's own ViewModel that contains the logic specific to that piece of UI. The ViewModel will make use of services to achieve what the user is requesting through their interactions.

Services is where all the actual work happens. ViewModels make use of the services but doesn't contain any hard functionality outside of conditionals and calling services. So, to get to the task at hand. We'll have an Authentication service that we'll use to sign in or sign up with that will store an instance of the current firebase user for us to use when required. We will have two views, Login and SignUp view which will make of the two functions on the service. The entire backend of the application will be built using Firebase so make sure to go to your console and login with a gmail account.

Setup Firebase Project

Open up the firebase console and click on "Add Project". Call it "compound", go next, select your account and then create. This will take a few seconds to setup. When it's complete click on continue and you'll land on the overview page.

Click on the Android Icon (or iOS) and add your package name, I'll set mine to com.filledstacks.compound. I'll set the nickname to "Compound". Register the app and then download the google-services.json file. If you have your own project or want to use my starting code, which you can download here, open up the code and place the google-service.json file in the android/app folder. Then open the build.gradle file in the android/app folder and change the applicationId to match the one you entered for your Firebase project.

Setup in code

Open up the pubspec.yaml and add the firebase_auth plugin.

firebase_auth: ^0.15.3

Then we have to enable the google services. Open the build.gradle file in the android folder and add the google services dependency.

    dependencies {
        // existing dependencies
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // Add the google services classpath
        classpath 'com.google.gms:google-services:4.3.0'
    }

Open up the android/app/build.gradle file and apply the google services plugin. Add the following line at the bottom of the file.

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'

That's it for the Android setup. Lets continue with the Firebase project. Once you've created the app you can go next and skip the firebase comms check that they do. On the left hand side, click on the Authentication Icon. The third icon from top (might change). Click on the Setup sign in methods button and click on email / password and enable it. That's it for the project setup, we'll get back to the Firebase console in the next episode.

Authentication Implementation

The starting code that I provided has a few things setup already.

  1. It contains the provider_architecture package which we use for the MvvmStyle bindings.
  2. It has an InputField widget which is styled how I want it.
  3. It has the locator for get_it setup like this
  4. It has a Navigation Service so we can navigate from the ViewModels and other services
  1. It has a Dialog Service for showing default dialogs
  1. It has the login view as well as the sign up view created and styled.

This is to make sure we keep the app to the point and only show the firebase parts. We'll be creating the Authentication service and then using it in the viewmodels, which are completely empty.

Authentication Service

The responsibility of the AuthenticationService in this case is to wrap the Firebase Authentication functionality for us. It will send the info we entered, and then tell us if it's successful or not. If it fails we return an error message to show the user. Under the services folder create a new file called authentication_service.dart.

import 'package:flutter/foundation.dart';

class AuthenticationService {
  Future loginWithEmail({@required String email, @required String password}) {
    // TODO: implement loginWithEmail
    return null;
  }

  Future signUpWithEmail({@required String email, @required String password}) {
    // TODO: implement signUpWithEmail
    return null;
  }
}

We'll start off keeping a reference to the FirebaseAuth instance locally. Then we'll perform signInWithEmailAndPassword and store the result in a variable called user. If there's no errors we'll check if the user is not null and return that value. If it fails we return the message from the error.

final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

Future loginWithEmail({
    @required String email,
    @required String password,
}) async {
    try {
        var user = await _firebaseAuth.signInWithEmailAndPassword(
            email: email, password: password);
        return user != null;
    } catch (e) {
        return e.message;
    }
}

Sign up looks very similar. The only difference is that the result of the createUserWithEmailAndPassword function returns a FirebaseAuth object instead of the user like login.

Future signUpWithEmail({
    @required String email,
    @required String password,
}) async {
    try {
        var authResult = await _firebaseAuth.createUserWithEmailAndPassword(
            email: email, password: password);
        return authResult.user != null;
    } catch (e) {
        return e.message;
    }
}

That's it for the AuthenticationService. Open up the locator.dart file and register the service as a lazy singleton. All that means is that there will only ever be 1 authentication service in existence, and we'll lazily create it once it has been requested the first time.4

void setupLocator() {
  locator.registerLazySingleton(() => NavigationService());
  locator.registerLazySingleton(() => DialogService());
  locator.registerLazySingleton(() => AuthenticationService());
}
Signup Logic

We'll start with sign up so that we can then perform a login afterwards. Open up the main.dart file and make sure home is set to SignUpView. Then open up the signup_view_model.dart file. We'll start by retrieving the AuthenticationService, NavigationService and DialogService from the locator. Then we'll create a function called SignUp that takes the email and password. In this function we'll set the view to busy before requesting, do the sign up. Then check the result, if it's a bool and it's true then we navigate to the HomeView. If it's false we'll show a general dialog, if it's a string we'll show the content as a dialog.

class SignUpViewModel extends BaseModel {
  final AuthenticationService _authenticationService =
      locator<AuthenticationService>();
  final DialogService _dialogService = locator<DialogService>();
  final NavigationService _navigationService = locator<NavigationService>();

  Future signUp({@required String email, @required String password}) async {
    setBusy(true);

    var result = await _authenticationService.signUpWithEmail(
        email: email, password: password);

    setBusy(false);
    if (result is bool) {
      if (result) {
        _navigationService.navigateTo(HomeViewRoute);
      } else {
        await _dialogService.showDialog(
          title: 'Sign Up Failure',
          description: 'General sign up failure. Please try again later',
        );

      }
    } else {
      await _dialogService.showDialog(
        title: 'Sign Up Failure',
        description: result,
      );
    }
  }
}

Open up the SignUpView file. Update the BusyButton to take in the busy property from the model and in the onPressed function call model.signUp.

 BusyButton(
    title: 'Sign Up',
    busy: model.busy,
    onPressed: () {
        model.signUp(
        email: emailController.text,
        password: passwordController.text,
        );
    },
)

If you run the app now, enter some details and login you'll see it navigate to the HomeView. If you want to see the error dialog enter a password with less than 6 characters and you'll see the dialog pop up. Also if you've already signed up you can try signing up with the same email again and you'll get a friendly error message :)

Login Logic

The login logic logic is literally exactly the same as the sign up logic. Being able to refactor for shared code is a good skill to have, I'll leave it up to you as an exercise to do. For now we'll write non dry code by simple repeating the pattern. Open up the login_view_model.dart

class LoginViewModel extends BaseModel {
  final AuthenticationService _authenticationService =
      locator<AuthenticationService>();
  final DialogService _dialogService = locator<DialogService>();
  final NavigationService _navigationService = locator<NavigationService>();

  Future login({@required String email, @required String password}) async {
    setBusy(true);

    var result = await _authenticationService.loginWithEmail(
        email: email, password: password);

    setBusy(false);

    if (result is bool) {
      if (result) {
        _navigationService.navigateTo(HomeViewRoute);
      } else {
        await _dialogService.showDialog(
          title: 'Login Failure',
          description: 'Couldn\'t login at this moment. Please try again later',
        );
      }
    } else {
      await _dialogService.showDialog(
        title: 'Login Failure',
        description: result,
      );
    }
  }
}

Open the login view. Pass the busy value to the BusyButton and in the onPressed function call the login function.

 BusyButton(
    title: 'Login',
    busy: model.busy,
    onPressed: () {
        model.login(
            email: emailController.text,
            password: passwordController.text,
        );
    },
)

Open up the main.dart file and change home to LoginView. If you re-run the code now you'll land on the LoginView. Enter the details you entered, click login and you're done :) . This is just the start of the app, we'll add functionalities a normal app would have throughout the rest of the series. In the next tutorial we'll make sure once we're signed in we go straight to the HomeView. We'll also create a user profile, make sure it's always available when the app is open and add roles (for later use ;) ).

I decided to ask you guys to start sharing the tutorials more, I'm still seeing some unmaintainable code when new clients come to me. We have to spread the architecture and code quality love around and make that the core focus when building apps. Until next time, Dane Mackier.

How to Create Liquid Swipe Animation in Flutter | Liquid Swipe Flutter

How to Create Liquid Swipe Animation in Flutter | Liquid Swipe Flutter

Today tutorial, I am going to show you how to create Liquid Swipe Animation in Flutter. liquid Swipe animation is amazing and its Created for iOS Platform and f

Today tutorial, I am going to show you how to create Liquid Swipe Animation in Flutter. liquid Swipe animation is amazing and its Created for iOS Platform and for React Native Platform. this animation Or Liquid Swipe Animation is Inspired by Cuberto.

Cuberto Liquid Swipe Animation

For this animation, we are will Need liquid_swipe Package. Liquid Swipe is the Unveils a New Page like Liquid Animation Just like the Above animation.

📱 What we're going to Build

How to Create Liquid Swipe Animation in Flutter

Let's Start the Tutorial

If you Don't know how to Create a Flutter app, check out Getting started with Flutter official tutorial.

Read More

11 Best Flutter Development Tools You Will Need As A Beginner | AllTechSavvy

11 Best Flutter Development Tools You Will Need As A Beginner | AllTechSavvy

In this tutorial, I am going to show you some of the Best Flutter development tools available in the market which will help you to make Development Produc

In this tutorial, I am going to show you some of the Best Flutter development tools available in the market which will help you to make Development Productivity Faster and Build Better Applications. Flutter is a Framework from google for Creating Cross-platform mobile apps.

Flutter is a Google UI Framework for Developers to Create Native applications for Mobile, Web, and Desktop Just in a Single Codebase. Flutter is Used by Millions of Developer Worldwide to create beautiful UI for their applications.we’ll look at some of the Best flutter development tools that can greatly improve your workflow and help you reduce development time.

Okay Without wasting any time. Let’s start in and Discover lots of New & awesome Flutter tools to develop your flutter apps like a legend.

Best Flutter Development Tool

#11. panache
Panache will help you to create beautiful themes for your flutter apps, you can customize colors & shapes in the apps.

Website: https://rxlabz.github.io/panache

#10.Codemagic
Codemagic is another awesome tool that’ll boost your flutter app development process. Cinemagic will test and release your flutter apps without issue & with no configuration. with the help Codemagic, you can automate the whole build process, test and release process of your flutter apps

Website: codemagic.io

#9.Appetize
Appetize is an Online web-based android Emulator and iOS simulator. Appetize will run Native mobile Apps in the browser with HTML and Javascript. which is easy to maintain and tacks.

Website: appetize.io

#8.TestMagic
TestMagic is a Free Companion app just like Codmagic for Fast & Easy testing of your android and iOS builds. Testmagics helps to distribute your builds and Testing android and Ios Apps on real devices as well as provide Feedback to your projects.

Website: testmagic.io

#7. Screenshots
A screenshot is a command-line utility for capturing Screenshots into the status bar placed in the device frame. Screenshots can be integrated into flutter to work transparently into Android and iOS.

Website: https://github.com/mmcc007/screenshots

#6.Supernova
Supernova Recently Introduced Support For Flutter Platform in Flutter interact. Supernova is a tool that helps you to Generate UI Code for Flutter. it’s support for material Design widgets a style manage that can bring the concepts of token and style into a flutter, you can have flutter app running side by side with Supernova and Change happen real-time.

Supernova will save your time by importing your Sketch Or Adobe Xd file, Select flutter as your export platform which will convert UI design into Production-ready Code.

Website: supernova.io

#5. Adobe Plugins For Flutter
Adobe Recently Released Plugins for Adobe Xd in Flutter Interact, which will Generate Code for Creating apps with flutter which is based on UI design in Adobe XD. this is Collaboration Between Google and Adobe that will be Expected to Released Early 2020. So Plugins will be Open Source According to Adobe.

Website: theblog.adobe.com

Read more