Login And Sign up with Bloc & Firebase in Flutter for Beginners


Hi everyone, I am Hemang<Mr. Ed>

Today we look into how login and signup work with firebase and how we handle state with the use of bloc in a flutter this blog is quite long but you will get what you really want.

Let’s start with one Tip, if you are like me one who always learner something — it will change the way you learn.

The method called High Order learning — I will not go deep into it because I know you come here to learn flutter but if you want the best search it in google.

So it says that to learn anything only understanding of that thing is not enough if you can’t explain it very well to someone and apply it in the real world if you can do this bro you mastered it And one more thing I want to add in India we always give advice to children that “ if you share more you will get more “ so keep sharing knowledge and help someone who is sharing if you can’t help appreciate it. It helps a lot.

so let's start code,

-> First create a flutter project by typing the below command in the terminal.

flutter create app_name

# Part — 1 > Firebase Set_up.

-> Step 1> Now we need to configure firebase with our project.

- Go to https://firebase.google.com/

- Create your project give it a name and choose one from suggestions boom your project is almost ready to configure with a project.

-> Step 2> Now you need to Install Firebase CLI.

- To install that simply write the below command in the terminal

npm install -g firebase-tools


OR visit the below website.

https://firebase.google.com/docs/cli#setup_update_cli


- If you successfully install CLI, Now Login to firebase by below command

firebase login

- Install the FlutterFire CLI by running the following command from any directory:

dart pub global activate flutterfire_cli

If you are getting an error may check the below directories in ENV

C:\Users\’your user name’ \AppData\Local\Pub\Cache\bin

C:\Users\’your user name’\AppData\Roaming\Pub\Cache\bin

# Part — 2 > Project Set_up.

  • Step 3> It’s Time to Add some Needed Packages.

Use flutter pub add to add the below packages in your project.

- firebase_core

- firebase_auth

- flutter_bloc

- page_transition

- equatable

- To Configure your app to use Firebase by the following command

flutterfire configure

Select your project from given

Step 4> Now it’s time to add some dependency in build_gradle .

Step 5> SetUp your main.dart file

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';


import 'bloc/app_bloc.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
// options: const FirebaseOptions(
// apiKey: " ",
// appId: " ",
// messagingSenderId: " ",
// projectId: " ",
// ),
);
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlaySt
statusBarColor: Colors.transparent,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.dark));
return BlocProvider(
create: (context) => AppBloc(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const WelcomeScreen(),
),
);
}
}

https://github.com/mred0/VittMaya/blob/master/lib/main.dart

# Part — 3> FirebaseAuthentication Set_up.

  1. Enable Authentication from firebase website.

2.Now Add auth folder and in it add firebase authentication function like this.

import 'package:firebase_auth/firebase_auth.dart';

class Auth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

User? get currentUser => _firebaseAuth.currentUser;

Stream<User?> get authStateChanges => _firebaseAuth.authStateChanges();

Future<void> signInWithEmailAndPassword(
{required String email, required String password}) async {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
}

Future<void> createUserWithEmailAndPassword(
{required String email, required String password}) async {
await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
}

Future<void> sendResetPasswordEmail({required String email}) async {
await _firebaseAuth.sendPasswordResetEmail(email: email);
}

Future<void> signOut() async {
await _firebaseAuth.signOut();
}
}
  • also create new class auth_error.dart and add this,
String authErrorlogin='';
String authErrorRegister='';

https://github.com/mred0/VittMaya/tree/master/lib/auth

# Part — 4> Bloc Set_up.

Now it’s time to add bloc code in project.

create bloc folder from vs_code like this.

  1. We add blocEvent in It we initialize 4 event class which extends to it’s parent class app_event.
  • AppEventLogIn
  • AppEventRegister
  • AppEventResetPassword
  • AppEventLogOut
part of 'app_bloc.dart';

abstract class AppEvent extends Equatable {
const AppEvent();
}

@immutable
class AppEventLogIn extends AppEvent {
final String email;
final String password;

const AppEventLogIn({required this.email, required this.password});

@override
// TODO: implement props
List<Object?> get props => [email, password];
}

@immutable
class AppEventRegister extends AppEvent {
final String email;
final String password;
const AppEventRegister({required this.email, required this.password});

@override
// TODO: implement props
List<Object?> get props => throw UnimplementedError();
}

@immutable
class AppEventResetPassword extends AppEvent {
final String email;

const AppEventResetPassword( {required this.email});

@override
// TODO: implement props
List<Object?> get props => [email];
}

@immutable
class AppEventLogOut extends AppEvent {
const AppEventLogOut();

@override
// TODO: implement props
List<Object?> get props =>throw UnimplementedError();
}

https://github.com/mred0/VittMaya/blob/master/lib/bloc/app_event.dart

2. Now we Add 2 states classes in the app_state class.

in app_state we declare 2 bool isLoading and successfully.

  • AppStateLoggedIn
  • AppStateLoggedOut
part of 'app_bloc.dart';

abstract class AppState extends Equatable {
final bool isLoading;
final bool successful;
const AppState({required this.isLoading, required this.successful});
}

class AppStateLoggedIn extends AppState {
AppStateLoggedIn({
required isLoading,
required successful,
}) : super(isLoading: isLoading, successful: successful);

@override
List<Object> get props => [isLoading, successful];
}

class AppStateLoggedOut extends AppState {
AppStateLoggedOut({
required isLoading,
required successful,
}) : super(isLoading: isLoading, successful: successful);

@override
List<Object> get props => [isLoading, successful];
}

https://github.com/mred0/VittMaya/blob/master/lib/bloc/app_state.dart

3. Int the Last we configure 4 on<> event methods which change the states.

import 'dart:developer';
import 'dart:ui';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';



part 'app_event.dart';
part 'app_state.dart';

class AppBloc extends Bloc<AppEvent, AppState> {
AppBloc() : super(AppStateLoggedOut(isLoading: false, successful: false)) {
on<AppEventLogIn>((event, emit) async {
emit(AppStateLoggedOut(isLoading: true, successful: false));
try {
await Auth().signInWithEmailAndPassword(
email: event.email, password: event.password);
emit(AppStateLoggedIn(isLoading: false, successful: true));
} on FirebaseAuthException catch (e) {
log("Exception on LogIn------------->${e}");
authErrorlogin = e.toString();
emit(AppStateLoggedOut(isLoading: false, successful: false));
}
});

on<AppEventLogOut>((event, emit) async {
emit(AppStateLoggedOut(isLoading: true, successful: false));
try {
await Auth().signOut();
emit(AppStateLoggedIn(isLoading: false, successful: true));
} on FirebaseAuthException catch (e) {}
});

on<AppEventRegister>((event, emit) async {
emit(AppStateLoggedOut(isLoading: true, successful: false));
try {
await Auth().createUserWithEmailAndPassword(
email: event.email, password: event.password);
emit(AppStateLoggedIn(isLoading: false, successful: true));
} on FirebaseAuthException catch (e) {
log("Exception on SignUp------------->${e}");
authErrorlogin = e.toString();
emit(AppStateLoggedOut(isLoading: false, successful: false));
}
});

on<AppEventResetPassword>((event, emit) async {
emit(AppStateLoggedOut(isLoading: true, successful: false));
try {
await Auth().sendResetPasswordEmail(email: event.email);
emit(AppStateLoggedIn(isLoading: false, successful: true));
} on FirebaseAuthException catch (e) {
log("Exception on LogIn------------->${e}");
authErrorlogin = e.toString();
emit(AppStateLoggedOut(isLoading: false, successful: false));
}
});
}
}

https://github.com/mred0/VittMaya/blob/master/lib/bloc/app_state.dart

-> Let’s Understand what is happening here.

Initially, ApplogoutState is isLoading and successfully are false.

  1. When we call Login Event it emits to logged-out state. so now you are logged in so you can logged-out yourself so isLoading is true and yet you did not log_out so successful is false. so in the try, it will try to log in by calling the firebase signInWithEmailAndPassword method if it succeeds it changes the state of login to isLoading false and successfully true else if it does not succeed it will throw an error and we will store it in our authErrorlogin and show it on our page.
  2. When we call LogOut Event it emits and changes the logout state to isLoading is false and successfully true and in a try, it calls the signout method if fails it throws an error.
  3. When we call Register Event it emits to logged-out state. so now you are Register so you can logged-out yourself so isLoading is true and yet you did not log_out so successful is false. so in the try, it will try to Register in by calling the firebase createUserWithEmailAndPassword method if it succeeds it changes the state of login to isLoading false and successfully true else if it does not succeed it will throw an error and we will store it in our authErrorlogin and show it on our page.
  4. As same for resetting password.

Now For UI, I will not go deep but If We Want to change the UI on state change we wrap the class or particular code with BlocBuilder<AppBloc, AppState>. my GitHub code link is given below check that out at the end.

We call events like below.

  • for sign_up
context.read<AppBloc>().add(AppEventRegister(
email: emailController.text,
password: passwordController.text));

https://github.com/mred0/VittMaya/blob/master/lib/screens/sign_up_screen.dart

  • for login
context.read<AppBloc>().add(AppEventLogIn(
email: emailController.text,
password: passwordController.text));

https://github.com/mred0/VittMaya/blob/master/lib/screens/login_screen.dart

  • for reset password
 context.read<AppBloc>().add(
AppEventResetPassword(
email: emailController
.text));

https://github.com/mred0/VittMaya/blob/master/lib/screens/login_screen.dart

  • for log_out
context.read<AppBloc>().add(const AppEventLogOut());

So I am Creating a Personal Finance management app with the use of bloc, firebase, hive, and rive as well so I can learn it also I can handle my finance as well. So I will create a blog for it as well if you liked it please follow me and If you have any suggestions for me I would like to here.

GitHub code link:- https://github.com/mred0/VittMaya

follow me on LinkedIn:- https://www.linkedin.com/in/hemang-rathod-%C2%AB%E2%9F%A8%D0%BC%D1%8F-%EA%8D%9F%EA%80%B8%E2%9F%A9%C2%BB-7a08aa233/

Thank you.

Comments