Hi Everyone! Welcome back to the MVVM series and in this
video we will setup the Room Database in our project. Now again if you want to learn Room in detail
then you can click here to go through Android Room Course. Because in this video I will quickly setup
the Room. Now the main question is "Why we need Room?". As in our project we are trying to implement
the user login feature, so how do we know a user is authenticated. If we talk about web app then there we have
a session but in our mobile app we do not have a session, so what we do is we call the
API and if we get the response as user authenticated that we are getting here, the user is authenticated
if we pass the correct email and password we store the user information in local database. And if a user is stored in the local database
we assume the user is logged in. And we are going to do the same thing in our
project. But in terms of security it is really a bad
practice. But as we are learning we will do like this. But let me also tell you about what actually
happens in production applications. So our API gives a token on successful login,
and that is saved and the token is valid for a specific time. And when the user logs out the token is invalidated. But here we are not going to make things complicated
so we will just store the user in SQLite database. And to operate the SQLite database I want
to use Room here. So enough talking guys, let's get started. But before starting, if you are not already
a subscriber, please subscribe to the channel and don't forget to hit the bell icon so that
you are always notified about my new videos. So coming back to our project inside our data
package I will create one more package here and I will name it db. And I will store all the local database related
classes or files here. Inside db I will create a kotlin file or class
and I will name it AppDatabase and this is a class, kotlin class. Then inside this package I will create one
more package to store all the database entities. So we have the entities, now inside the entities
package I will create one more class to store the user. And let's create kotlin file class and name
it User. And it is a class. Because right now in our project we have only
one entity and it is our User entity. Now we need to define our User class to map
these values that we are getting in the login response. So let's do it. I will make a data class here and this class
do not need a body. And to this class I will define all the values
that are required for our User. The first thing that we need is a var of type
Int and the name of this var is id. So I will name var id of type Int and the
initial value would be null. Then again I will define name of type String
and the initial value is null. And the same way I will define all the other
variables. So we have all the variables that are required
to map our User to this class. Now I will delete this thing we don't need
it now. Now as this class is an entity for our Room
Database we need to annotate this class with the annotation @Entity. And if you want to change the table name in
your room database you can define a table name here. But I don't want to change the table name
so I will keep it like this. And above this I will define a constant val
and I wil name it CURRENT_USER_ID and for the value I will write 0, as we want to store
only the authenticated user in our local database we do not need to make the ID auto increment,
because we don't want to store multiple users for now. So for this user table, I will define the
primary key as autoGenerate false and I will put the constant value that we defined here. And in case of any conflict I will replace
and overwrite the currently saved user, because only the authenticated user is stored in our
Application. So there is only one user in the local database. And that is why I will define a primary key
here in the class body and I will make it a var and I will name it uid and the type
is again Int and the current value is CURRENT_USER_ID and I will make it primary key with the help
of @PrimaryKey annotation and I will make it the autoGenerate to false, that's it. So we have our entity class ready. Now to handle the database operation for this
User table we need to create a Dao, which is data access object. So inside our db package we will create one
more Kotlin file class, and we will name it UserDao. And because this is a dao we need to create
an interface. So let's create interface UserDao and we need
to annotate it with @Dao annotation. And that means this interface is a data access
object. Now here I will define two functions the first
function is to insert or update the user. So I will create fun upsert() that means insert
or update. Or you can name your functions anything, the
name doesn't matter at all. And inside this function we will pass User,
which is our entity so we have the user and this function will return us a Long. So in case a user is successfully inserted
we will get the inserted row id with the help of this Long so that is why Long is the return
type of this function. Now this function will perform the insert
operation in our database, that is why we need to annotate it with the @Insert annotation. And inside this insert we will define what
we need to do when there is a conflict, that means we want to insert the same id again
or the same primary key again. So in this case we will right Conflict Strategy
which is OnConflictStrategy.REPLACE. So we will overwrite the currently saved user
with the new one in case of conflict. Now I will need one more function here and
this function will give us back the stored user. So that is why I need to annotate this function
with @Query and for the query we will write "SELECT * FROM User WHERE uid = $CURRENT_USER_ID"
that we already defined in our entity class. So we need to import the CURRENT_USER_ID so
it is imported from the entities. So we have the annotation now we will create
a function fun getUser() and this function will return us a LiveData of type User, that's
it. So we have all the functions that are required
for our UserDao. Now let's come back to AppDatabase and create
our Database. Now whenever you are creating a database class
for Room you need to make it abstract and you need to extend RoomDatabase. Then you need to put an annotation which is
@Database and inside this annotation you need to define all the entities that you have. So in our case we have only a single entity
that is User.class actually User::class, so this is how we define the entities. And this is an array so you can define as
many entities as you want. And for the next parameter, we will define
the version of our database so in my case it is the first version. Now inside your class you need to create the
abstract functions for all your Daos. So in our case we have only a single Dao. I will create here abstract fun getUserDao()
and it will return us a UserDao, which is our interface that we just created. Now after declaring all the Dao functions
I will create a companion object to create our AppDatabase and inside the companion object
first I will create a private var and I will name it instance and this is the instace of
our AppDatabase and the initial value is null and I will make this instace as @Volatile. And @Volatile annotation in kotlin means this
variable is immediately visible to all the other threads. So that is why it is @Volatile now after this
instace variable I will create a private val LOCK and it is of type Any. And I will use this LOCK to make sure we do
not create two instances of our Database. Now we will create an operator fun invoke()
and this function will take context because we need context to create the database. So when we create the AppDatabase we will
pass the context to this invoke and this invoke will first check if this instance is not null
so if this instance is not null it will return the instance and with the help of this operator
we can immediately return the instance if it is not null if it is null it will come
here and here we will create a synchronized block with this LOCK val that we created. Inside the synchronized block again we will
check if the instance is not null and if it is null then in that case we will call a function
that is buildDatabase() and to this function we will pass context, now let's create buildDatabase()
first, so here inside the companion object we will create private fun and it is buildDatabase()
and it will take context and it will build the database for us so we will write = Room.databaseBuilder()
now this databaseBuilder function takes three parameters, the first parameter is the context
and we have the context here and when we want to build the database we will use context.applicationContext
to always pass the applicationContext. So even if we pass the context from a fragment
it will take the applicationContext. Now for the next parameter we need to pass
our abstract class that is extending the RoomDatabase so here we will pass AppDatabase::class.java. And for the last parameter we need to pass
the database name, so I will create a database named MyDatabase.db or you can name it anything
and then finally we will call the build() function to build our database. Now this function is returning us the database,
so we are calling it here to build the database and we are passing the context that we received
in this invoke() now we will call also and we will assign the returned value of this
buildDatabase that is our database actually to this instance. So we need to write here instance = it. And our database is created. Now we can use this AppDatabase to get the
UserDao and then from the UserDao we can save our User to our Database. But for this we need to parse the response
because currently we are getting the response in a raw string format, and we will parse
the response in the next video. So that is all for this video friends. In the next video we will finally use this
Room to save the logged in user. In case you have any difficulties you can
let me know in comments. Because it is very important that you complete
every lesson of this course successfully. And if you are loving this course then please
promote this course to your friends as well. Thanks for watching everyone this is Belal
Khan now Signing Off.