Simplified Coding

  • About
  • Contact Us
  • Advertise
  • Privacy Policy
Home » Firebase MVVM Example – Implementing Authentication

Firebase MVVM Example – Implementing Authentication

July 16, 2019 by Belal Khan 2 Comments

Recently we finished learning the MVVM Design Pattern in Android App Development, and while learning that we used RESTful APIs to communicate with our Back End. But sometimes we do create server less application using Firebase. And some people asked that “How do I follow MVVM when using Firebase?“.  That is why in this Firebase MVVM Example we will learn implementing the Firebase Authentication with MVVM Design Pattern.

Contents

  • 1 Prerequisites
  • 2 Creating an Android Project
  • 3 Adding Required Dependencies
  • 4 Adding Firebase Authentication
  • 5 Enabling Data Binding
  • 6 Creating Packages
  • 7 Creating Activities
  • 8 Creating Firebase Source
  • 9 Creating User Repository
  • 10 Creating an AuthListener
  • 11 Creating AuthViewModel and Factory
    • 11.1 AuthViewModel
    • 11.2 AuthViewModel Factory
  • 12 Designing UI and Binding Data
    • 12.1 Login Activity
    • 12.2 Signup Activity
  • 13 Functions for Switching Between Login and Home Activity
  • 14 Creating Dependency Provider using Kodein
  • 15 Binding ViewModel and Activities
    • 15.1 LoginActivity
    • 15.2 Signup Activity
  • 16 Finishing Up Home Activity
    • 16.1 Creating HomeViewModel and HomeViewModelFactory
    • 16.2 Designing UI
    • 16.3 Binding HomeViewModel and HomeActivity
  • 17 Firebase MVVM Example Source Code
    • 17.1 Sharing is Caring:
    • 17.2 Related

Prerequisites

If you are an absolute newbie and accidentally came here then, I would like to tell you that this post is not for you. Before moving ahead in this post you should already know these things.

  1. What is MVVM Design Pattern?
  2. How to implement Firebase Authentication

If you don’t know these things, then take your time and go through the above courses first. Then you can follow this. And if you are brave enough to follow it without the above mention courses, then that’s awesome let’s start. And one thing I forgot, we also need a little bit of RxJava and RxAndroid.

Creating an Android Project

As always we need to create a new Android Studio Project. Here, I am creating a project named “Firebase Auth MVVM”. You can change the name if you want. But make sure you have the following settings while creating the project.

Firebase MVVM Example

Firebase MVVM Example

Once your project is loaded, we will start adding the required dependencies.

Adding Required Dependencies

First add the following in your app level build.gradle file. You need to add all these lines inside dependencies block.

1
2
3
4
5
6
7
8
9
10
11
12
13
    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
 
    //New Material Design
    implementation 'com.google.android.material:material:1.1.0-alpha07'
 
    //Kodein Dependency Injection
    implementation "org.kodein.di:kodein-di-generic-jvm:6.2.1"
    implementation "org.kodein.di:kodein-di-framework-android-x:6.2.1"
 
    //RxJava
    implementation "io.reactivex.rxjava2:rxjava:2.2.5"
    implementation "io.reactivex.rxjava2:rxandroid:2.1.0"

As you can see we are going to use ViewModel, LiveData, Material Design, Kodein Dependency Injection and RxJava. But other than all these dependencies, the most important thing that we need is the Firebase. And we did not add this yet. But don’t worry sync the project for now.

Adding Firebase Authentication

Now adding firebase is very easy and I already discussed it many times in videos and post. So I think no point of explaining the same thing again and again. You can go to Tools -> Firebase to add firebase authentication in Android Studio. Still you have confusion then you can just check this link where I added Firebase Cloud Messaging. But you don’t need to add cloud messaging, you need to add Authentication. So just select Authentication instead of Cloud Messaging and the process is same.

Enabling Data Binding

As we are going to implement the Model View ViewModel design pattern and data binding is a key point of this pattern. So let’s enable data binding.

  • Again go to app level build.gradle file and enable data binding by adding following code inside android block.

1
2
3
    dataBinding {
        enabled = true
    }

  •  After this inside the file gradle.properties add this line at the bottom.

1
android.databinding.enableV2=true

  • Now finally sync your project and we are good to go.

Creating Packages

Organizing the codes in different packages properly is very important thing, if you don’t want to bang your head, when you need to open different files of your project. haha 😀 . So first we will create the following package structure in our Android Studio. Just to make the things well organized.

Firebase MVVM Example

Firebase MVVM Example

As you can see I have created thre main packages

  1. data: Inside this package we will store the models and the repositories. So again we have two more packages inside this package.
  2. ui: All the UI related things will go inside this package (Activities, Fragments, ViewModels, Adapters etc). Inside this package we have two more packages for the Auth and for the Home screen of our application.
  3. utils: Inside this package we will store the helper functions.

Now finally refactor your MainActivity as LoginActivity and activity_main.xml as activity_login.xml. Because the MainActivity is our LoginActivity and changing a sensible name is always a good idea. So refactor both xml and kotlin file for the activity and we are good to go.

Creating Activities

In this project we basically need three activities. For Login, for Signup and for Home. We already have the Login and we need to create the Home and the Signup Activity. So create empty activities in Auth and Home Package as shown in the below image.

Firebase MVVM Example

Firebase MVVM Example

So when the user is authenticated either from Login or Signup activity, we will display the HomeActivity.

According to the MVVM Design Rule, our View can communicate with ViewModel, ViewModel can communicate with Repository and Repository can communicate with our Back End, which is in this case Firebase.

So first we will create a Firebase class to handle Firebase operations.

Creating Firebase Source

  • Inside your data package create one more package named firebase. And inside this package create a class named FirebaseSource.

FirebaseSource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class FirebaseSource {
 
    private val firebaseAuth: FirebaseAuth by lazy {
        FirebaseAuth.getInstance()
    }
 
 
    fun login(email: String, password: String) = Completable.create { emitter ->
        firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
            if (!emitter.isDisposed) {
                if (it.isSuccessful)
                    emitter.onComplete()
                else
                    emitter.onError(it.exception!!)
            }
        }
    }
 
    fun register(email: String, password: String) = Completable.create { emitter ->
        firebaseAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener {
            if (!emitter.isDisposed) {
                if (it.isSuccessful)
                    emitter.onComplete()
                else
                    emitter.onError(it.exception!!)
            }
        }
    }
 
    fun logout() = firebaseAuth.signOut()
 
    fun currentUser() = firebaseAuth.currentUser
 
}

  • As you can see in the above class we have 3 functions, for login, signup, logout and getting the currently logged in user. The code is pretty much self explanatory, and it is almost the same as we do with Firebase. The only difference here is, we are using Completable that is an RxJava class.  Completable basically means it holds something that will complete and we can get an indication when it is completed or failed. And it is the perfect class to use with FirebaseAuth because auth is a network operation that will complete and we need to know if it is completed or failed.
  • So here we are creating a Completable and inside the completable we are performing the authentication. Once it is completed we are using the emitter to indicated that the task is completed or failed. Fairly simple, I guess. 

So we have the FirebaseSource, and now we need a Repository so that we can communicate with the Firebase.

Creating User Repository

  • Inside the repositories package (which is inside data) create a new class named UserRepository. To the constructor of this class we will pass the FirebaseSource that we just created. And then with the help of firebase source, we will perform the operations needed.

UserRepository
1
2
3
4
5
6
7
8
9
10
11
class UserRepository (
    private val firebase: FirebaseSource
){
    fun login(email: String, password: String) = firebase.login(email, password)
 
    fun register(email: String, password: String) = firebase.register(email, password)
 
    fun currentUser() = firebase.currentUser()
 
    fun logout() = firebase.logout()
}

  • As you can see the code is very simple. We are just calling the functions, that we defined inside FirebaseSource.
  • Now we have the repository that will communicate with our backend. And we need a ViewModel that can communicate with the Repository.

But we also need an AuthListener here so that when the task is finished we can fire a callback inside our Activity, to determine what happened to the login or signup operation. 

Creating an AuthListener

  • Inside the auth package (that is inside ui) create an interface named AuthListener.

AuthListener
1
2
3
4
5
interface AuthListener {
    fun onStarted()
    fun onSuccess()
    fun onFailure(message: String)
}

  • Now we will create our ViewModel.

Creating AuthViewModel and Factory

AuthViewModel

  • Again inside the auth package create a new class named AuthViewModel.

AuthViewModel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class AuthViewModel(
    private val repository: UserRepository
) : ViewModel() {
 
    //email and password for the input
    var email: String? = null
    var password: String? = null
 
    //auth listener
    var authListener: AuthListener? = null
 
 
    //disposable to dispose the Completable
    private val disposables = CompositeDisposable()
 
    val user by lazy {
        repository.currentUser()
    }
 
    //function to perform login
    fun login() {
 
        //validating email and password
        if (email.isNullOrEmpty() || password.isNullOrEmpty()) {
            authListener?.onFailure("Invalid email or password")
            return
        }
 
        //authentication started
        authListener?.onStarted()
 
        //calling login from repository to perform the actual authentication
        val disposable = repository.login(email!!, password!!)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                //sending a success callback
                authListener?.onSuccess()
            }, {
                //sending a failure callback
                authListener?.onFailure(it.message!!)
            })
        disposables.add(disposable)
    }
 
    //Doing same thing with signup
    fun signup() {
        if (email.isNullOrEmpty() || password.isNullOrEmpty()) {
            authListener?.onFailure("Please input all values")
            return
        }
        authListener?.onStarted()
        val disposable = repository.register(email!!, password!!)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                authListener?.onSuccess()
            }, {
                authListener?.onFailure(it.message!!)
            })
        disposables.add(disposable)
    }
 
    fun goToSignup(view: View) {
        Intent(view.context, SignupActivity::class.java).also {
            view.context.startActivity(it)
        }
    }
 
    fun goToLogin(view: View) {
        Intent(view.context, LoginActivity::class.java).also {
            view.context.startActivity(it)
        }
    }
 
 
    //disposing the disposables
    override fun onCleared() {
        super.onCleared()
        disposables.dispose()
    }
 
}

  • And we have the ViewModel, now we just need to use DataBinding with our Activity.

AuthViewModel Factory

  • As we need the UserRepository inside the AuthViewModel we need a ViewModelFactory to generate the ViewModel with the required parameter.
  • So create one more class named AuthViewModelFactory inside the auth package.

AuthViewModelFactory
1
2
3
4
5
6
7
8
9
10
@Suppress("UNCHECKED_CAST")
class AuthViewModelFactory(
    private val repository: UserRepository
) : ViewModelProvider.NewInstanceFactory() {
 
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return AuthViewModel(repository) as T
    }
 
}

Designing UI and Binding Data

Login Activity

  • Go inside your activity_login.xml and paste the following code.

activity_login.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
>
 
    <data>
        <variable name="viewmodel"
                  type="net.simplifiedcoding.ui.auth.AuthViewModel"/>
    </data>
 
    <RelativeLayout android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#008577"
                    android:orientation="vertical"
                    tools:context=".ui.auth.LoginActivity"
                    android:scrollbarAlwaysDrawVerticalTrack="true">
 
        <RelativeLayout
                android:id="@+id/loginLayout"
                android:layout_centerInParent="true"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
 
            <TextView
                    android:id="@+id/login_title"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="16dp"
                    android:gravity="center_horizontal"
                    android:text="Account Login"
                    android:textColor="#fff"
                    android:textSize="26sp"
                    android:textStyle="bold"/>
 
            <RelativeLayout
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/login_title"
                    android:layout_marginLeft="30dp"
                    android:layout_marginRight="30dp"
                    android:layout_marginTop="70dp"
                    android:background="#fff"
                    android:elevation="4dp"
                    android:orientation="vertical"
                    android:padding="20dp">
 
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:paddingTop="30dp">
 
 
                    <TextView
                            android:labelFor="@id/text_email"
                            android:text="email"
                            android:fontFamily="sans-serif-light"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
 
                    <EditText
                            android:id="@+id/text_email"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:drawableLeft="@drawable/ic_email"
                            android:drawablePadding="10dp"
                            android:singleLine="true"
                            android:text="@={viewmodel.email}"
                            android:layout_marginBottom="10dp"
                            android:hint="john@gmail.com"
                            android:inputType="textEmailAddress"/>
 
                    <TextView
                            android:labelFor="@id/edit_text_password"
                            android:text="password"
                            android:fontFamily="sans-serif-light"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
 
                    <EditText
                            android:drawablePadding="10dp"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:singleLine="true"
                            android:text="@={viewmodel.password}"
                            android:id="@+id/edit_text_password"
                            android:drawableLeft="@drawable/ic_lock"
                            android:hint="Password"
                            android:inputType="textPassword"/>
 
 
                    <TextView
                            android:id="@+id/text_view_forget_password"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="right"
                            android:paddingTop="5dp"
                            android:text="Forgot Password?"/>
 
 
                    <Button
                            android:id="@+id/button_sign_in"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:layout_margin="22dp"
                            android:onClick="@{() -> viewmodel.login()}"
                            android:background="#d67601"
                            android:text="Log in"
                            android:textAllCaps="false"
                            android:textColor="#fff"
                            android:textSize="18sp"/>
 
                    <TextView
                            android:id="@+id/text_view_register"
                            android:layout_gravity="center_horizontal"
                            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
                            android:textAlignment="center"
                            android:onClick="@{(v) -> viewmodel.goToSignup(v)}"
                            android:text="Don't have an account.\nRegister Here"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
                </LinearLayout>
 
            </RelativeLayout>
 
            <ImageButton
                    android:id="@+id/user_profile_photo"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_below="@+id/login_title"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="16dp"
                    android:background="@drawable/user_profile_image_background"
                    android:elevation="4dp"
                    android:src="@drawable/ic_boy"/>
 
        </RelativeLayout>
 
        <ProgressBar
                android:id="@+id/progressbar"
                android:visibility="gone"
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
 
    </RelativeLayout>
 
</layout>

  • The above XML code will generate the following layout.
Firebase Authentication MVVM

Firebase Authentication MVVM

But I have used some drawable resources to design the above layout. And after copying and pasting you will see some error that those resources are missing. But don’t worry you can get my source code and all the resources at the end of this post. 

Also make sure inside the data tag, you have given your ViewModel path according to your project. 

Signup Activity

Now we will do pretty much the same thing in SignupActivity as well.

  • First copy the following XML inside activity_signup.xml. 

activity_signup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
>
 
    <data>
        <variable name="viewmodel"
                  type="net.simplifiedcoding.ui.auth.AuthViewModel"/>
    </data>
 
    <RelativeLayout android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#008577"
                    android:orientation="vertical"
                    tools:context=".ui.auth.SignupActivity"
                    android:scrollbarAlwaysDrawVerticalTrack="true">
 
        <RelativeLayout
                android:id="@+id/signupLayout"
                android:layout_centerInParent="true"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
 
            <TextView
                    android:id="@+id/login_title"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="16dp"
                    android:gravity="center_horizontal"
                    android:text="New User Signup"
                    android:textColor="#fff"
                    android:textSize="26sp"
                    android:textStyle="bold"/>
 
            <RelativeLayout
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/login_title"
                    android:layout_marginLeft="30dp"
                    android:layout_marginRight="30dp"
                    android:layout_marginTop="70dp"
                    android:background="#fff"
                    android:elevation="4dp"
                    android:orientation="vertical"
                    android:padding="20dp">
 
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:paddingTop="30dp">
 
 
                    <TextView
                            android:labelFor="@id/text_email"
                            android:text="email"
                            android:fontFamily="sans-serif-light"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
 
                    <EditText
                            android:id="@+id/text_email"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:drawableLeft="@drawable/ic_email"
                            android:drawablePadding="10dp"
                            android:singleLine="true"
                            android:text="@={viewmodel.email}"
                            android:layout_marginBottom="10dp"
                            android:hint="john@gmail.com"
                            android:inputType="textEmailAddress"/>
 
                    <TextView
                            android:labelFor="@id/edit_text_password"
                            android:text="password"
                            android:fontFamily="sans-serif-light"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
 
                    <EditText
                            android:drawablePadding="10dp"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:singleLine="true"
                            android:text="@={viewmodel.password}"
                            android:id="@+id/edit_text_password"
                            android:drawableLeft="@drawable/ic_lock"
                            android:hint="Password"
                            android:inputType="textPassword"/>
 
 
 
                    <Button
                            android:id="@+id/button_sign_up"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:layout_margin="22dp"
                            android:onClick="@{() -> viewmodel.signup()}"
                            android:background="#d67601"
                            android:text="Sign Up"
                            android:textAllCaps="false"
                            android:textColor="#fff"
                            android:textSize="18sp"/>
 
                    <TextView
                            android:id="@+id/text_view_register"
                            android:layout_gravity="center_horizontal"
                            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
                            android:textAlignment="center"
                            android:onClick="@{(v) -> viewmodel.goToLogin(v)}"
                            android:text="Already have an account.\nLogin Here"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"/>
                </LinearLayout>
 
            </RelativeLayout>
 
            <ImageButton
                    android:id="@+id/user_profile_photo"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_below="@+id/login_title"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="16dp"
                    android:background="@drawable/user_profile_image_background"
                    android:elevation="4dp"
                    android:src="@drawable/ic_boy"/>
 
        </RelativeLayout>
 
        <ProgressBar
                android:id="@+id/progressbar"
                android:visibility="gone"
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
 
    </RelativeLayout>
 
</layout>

  • This XML will generate the following design.
Firebase Authentication MVVM

Firebase Authentication MVVM

Again make sure that you have defined the correct path of the ViewModel inside the variable tag. 

We have the design ready, and now we just need to bind the ViewModel and View. But before doing this thing we need one more small thing. When the authentication is successful we need to start the HomeActivity and when the user logs out again we need to start the LoginActivity. And we don’t want to repeat the codes again and again, so for both these operation we will define two extension functions.

Functions for Switching Between Login and Home Activity

  • Create a new kotlin file inside util package and name it ViewUtils.kt.

ViewUtils.kt
1
2
3
4
5
6
7
8
9
10
11
fun Context.startHomeActivity() =
    Intent(this, HomeActivity::class.java).also {
        it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        startActivity(it)
    }
 
fun Context.startLoginActivity() =
    Intent(this, LoginActivity::class.java).also {
        it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        startActivity(it)
    }

  • We will use these functions for login and logout.
  • Now we can bind the ViewModel and Activites but before doing that we will use Kodein to create a Dependency Provider.

Creating Dependency Provider using Kodein

As you know, we should not make the classes dependent. And to make the classes independent we need to use the Dependency Injection pattern. And to do this we will be using the Kodein Framework that we already added.

  • So inside your main package create a new class named FirebaseApplication.

FirebaseApplication
1
2
3
4
5
6
7
8
9
10
11
12
class FirebaseApplication : Application(), KodeinAware{
 
    override val kodein = Kodein.lazy {
        import(androidXModule(this@FirebaseApplication))
 
        bind() from singleton { FirebaseSource()}
        bind() from singleton { UserRepository(instance()) }
        bind() from provider { AuthViewModelFactory(instance()) }
        bind() from provider { HomeViewModelFactory(instance()) }
 
    }
}

  • Now we need to define this class in our AndroidManifest.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools" package="net.simplifiedcoding">
 
    <application
            android:name=".FirebaseApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme" tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        <activity android:name=".ui.home.HomeActivity">
        </activity>
        <activity android:name=".ui.auth.SignupActivity">
        </activity>
        <activity android:name=".ui.auth.LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
 
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
 
</manifest>

  • And we are done.

Binding ViewModel and Activities

LoginActivity

  • Open LoginActivity and write the following code.

LoginActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class LoginActivity : AppCompatActivity(), AuthListener, KodeinAware {
 
    override val kodein by kodein()
    private val factory : AuthViewModelFactory by instance()
 
 
    private lateinit var viewModel: AuthViewModel
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        val binding: ActivityLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login)
        viewModel = ViewModelProviders.of(this, factory).get(AuthViewModel::class.java)
        binding.viewmodel = viewModel
 
        viewModel.authListener = this
    }
 
    override fun onStarted() {
        progressbar.visibility = View.VISIBLE
    }
 
    override fun onSuccess() {
        progressbar.visibility = View.GONE
        startHomeActivity()
    }
 
    override fun onFailure(message: String) {
        progressbar.visibility = View.GONE
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }
 
    override fun onStart() {
        super.onStart()
        viewModel.user?.let {
            startHomeActivity()
        }
    }
}

  • The code is very simple and straightforward, in case you are having trouble understanding anything, please comment.

Signup Activity

  • Now we will do the same thing inside SignupActivity as well.

SignupActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class SignupActivity : AppCompatActivity(), AuthListener, KodeinAware {
 
    override val kodein by kodein()
    private val factory : AuthViewModelFactory by instance()
 
    private lateinit var viewModel: AuthViewModel
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_signup)
 
        val binding: ActivitySignupBinding = DataBindingUtil.setContentView(this, R.layout.activity_signup)
        viewModel = ViewModelProviders.of(this, factory).get(AuthViewModel::class.java)
        binding.viewmodel = viewModel
 
        viewModel.authListener = this
    }
 
    override fun onStarted() {
        progressbar.visibility = View.VISIBLE
        Intent(this, HomeActivity::class.java).also {
            it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            startActivity(it)
        }
    }
 
    override fun onSuccess() {
        progressbar.visibility = View.GONE
        startHomeActivity()
    }
 
    override fun onFailure(message: String) {
        progressbar.visibility = View.GONE
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }
}

  • Now we just need to work on HomeActivity.

Finishing Up Home Activity

Creating HomeViewModel and HomeViewModelFactory

  • First create HomeViewModel inside the home package.

1
2
3
4
5
6
7
8
9
10
11
12
13
class HomeViewModel(
    private val repository: UserRepository
) : ViewModel() {
 
    val user by lazy {
        repository.currentUser()
    }
    
    fun logout(view: View){
        repository.logout()
        view.context.startLoginActivity()
    }
}

  • Again we need to create our ViewModelFactory because we are passing repository to the HomeViewModel. So create one more class named HomeViewModelFactory.

HomeViewModelFactory
1
2
3
4
5
6
7
8
9
10
@Suppress("UNCHECKED_CAST")
class HomeViewModelFactory(
    private val repository: UserRepository
) : ViewModelProvider.NewInstanceFactory() {
 
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return HomeViewModel(repository) as T
    }
 
}

  • And that’s it. Now let’s code the XML part of our HomeActivity.

Designing UI

  • Go inside activity_home.xml and write the following code.

activity_home.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable name="viewmodel"
                  type="net.simplifiedcoding.ui.home.HomeViewModel"/>
    </data>
 
    <RelativeLayout
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".ui.home.HomeActivity">
 
            <TextView
                    android:text="@{viewmodel.user.email}"
                    tools:text="probelalkhan@gmail.com"
                    android:textAppearance="@style/TextAppearance.AppCompat.Headline"
                    android:layout_centerInParent="true"
                    android:id="@+id/textViewEmail"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
 
            <Button
                    android:onClick="@{(v) -> viewmodel.logout(v)}"
                    android:text="Logout"
                    android:layout_centerHorizontal="true"
                    android:layout_below="@id/textViewEmail"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
 
    </RelativeLayout>
 
</layout>

  • Again make sure you have given the correct path of the HomeViewModel inside the variable tag. 

Binding HomeViewModel and HomeActivity

  • Again we will do the same thing, that we did for Login and Signup activity.

SignupActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class HomeActivity : AppCompatActivity(), KodeinAware {
 
    override val kodein by kodein()
    private val factory : HomeViewModelFactory by instance()
 
    private lateinit var viewModel: HomeViewModel
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)
 
        val binding: ActivityHomeBinding = DataBindingUtil.setContentView(this, R.layout.activity_home)
        viewModel = ViewModelProviders.of(this, factory).get(HomeViewModel::class.java)
        binding.viewmodel = viewModel
 
    }
 
}

  • And we are done. You can try running the application and it should work fine. For example you can check my APK to test, if yours is not working.

Download APK

Firebase MVVM Example Source Code

In case you are not able to follow through the tutorial, don’t worry you have my source code to cross check your project. And if still having problem comment below and I will try to help you out.


git hub repository
Get the Source Code

So that is all for this Firebase MVVM Example friends. I hope I taught you something new with this post. And if you think it is really useful then please support me by sharing this post with your friends. Thank You 🙂

Sharing is Caring:

  • Tweet
  • Share on Tumblr
  • More
  • Pocket
  • Print
  • Email

Related

Filed Under: Android Advance, Android Application Development Tagged With: firebase, firebase mvvm

About Belal Khan

I am Belal Khan, I am currently pursuing my MCA. In this blog I write tutorials and articles related to coding, app development, android etc.

Comments

  1. Md Mainuddin says

    July 16, 2019 at 2:18 pm

    This is post is very helpful. thank you so much brother

    Reply
  2. saquib says

    July 25, 2019 at 11:08 am

    what is meant by FirebaseAuth by lazy

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Search




Download our Android App

Simplified Coding in Google Play

About Me

Belal Khan

Hello I am Belal Khan, founder and owner of Simplified Coding. I am currently pursuing MCA from St. Xavier's College, Ranchi. I love to share my knowledge over Internet.

Connect With Me

Follow @codesimplified
Simplified Coding

Popular Tutorials

  • Android Login and Registration Tutorial with PHP MySQL
  • JSON Parsing in Android – Fetching From MySQL Database
  • Android Volley Tutorial – Fetching JSON Data from URL
  • Android Upload Image to Server using Volley Tutorial
  • Android TabLayout Example using ViewPager and Fragments
  • Retrieve Data From MySQL Database in Android using Volley
  • Android Navigation Drawer Example using Fragments
  • Retrofit Android Example – Fetching JSON from URL
  • Firebase Cloud Messaging Tutorial for Android
  • Android Volley Tutorial – User Registration and Login




Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy

About Simplified Coding

Simplified Coding is a blog for all the students learning programming. We are providing various tutorials related to programming and application development. You can get various nice and simplified tutorials related to programming, app development, graphics designing and animation. We are trying to make these things simplified and entertaining. We are writing text tutorial and creating video and visual tutorials as well. You can check about the admin of the blog here and check out our sitemap

Quick Links

  • Advertise Here
  • Privacy Policy
  • Disclaimer
  • About
  • Contact Us
  • Write for Us

Categories

Android Advance Android Application Development Android Beginners Android Intermediate Ionic Framework Tutorial JavaScript Kotlin Android Others PHP Advance PHP Tutorial React Native

Copyright © 2017 · Simplified Coding· All rights Reserved. And Our Sitemap.All Logos & Trademark Belongs To Their Respective Owners·

loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.