Kotlin Room Database example with ViewModel and Live Data

Last updated Oct 27, 2021

In this Android example tutorial we will work with Room database with update the Live data using ViewModel. In this ViewModel example we are creating the ViewModel object by passing arguments.

To pass arguments to ViewModel constructor we will use ViewModelFactory pattern. Handle the Live data update using LiveData Jetpack component.

In this example we will store Employee data in the Room Database and fetch all employees data from database and display them on the RecyclerView using viewmodel. To update the live data we use LiveData component.

 

Android Room database with ViewModel LiveData kotlin example

 

So let's implement Room database with ViewModel Live Data

 

Step 1: Create Android application in Android studio

Step 2: Add required dependencies in build.gradle file

def lifecycle_version = "2.3.1"
    //implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // ViewModel utilities for Compose
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"


    // Room support
    def room_version = "2.3.0"
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"

    // Anko Commons
    implementation "org.jetbrains.anko:anko-commons:0.10.5"

    // RecyclerView
    implementation 'androidx.recyclerview:recyclerview:1.2.1'

 

We added dependencies for Room Database, LiveData, ViewModel and RecyclerView

 

Step 3: Room Database Integration

To work with Room Database we need to create Room Database instance and Dao classes and Entities. Read more about Room Database in Android.

Create Room Database instance

Here we are creating the singleton instance for Room Database using kotlin companion object.

companion object{
        private var INSTANCE: RoomSingleton? = null
        fun getInstance(context:Context): RoomSingleton{
            if (INSTANCE == null){
                INSTANCE = Room.databaseBuilder(
                    context,
                    RoomSingleton::class.java,
                    "roomdb")
                    .build()
            }

            return INSTANCE as RoomSingleton
        }
    }

 

Create Employee Entity

Create our employee entity with two fields, id auto increment and name

package com.rrtutors

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "employeeTbl")
data class Emplyee(
    @PrimaryKey
    var id:Long?,

    @ColumnInfo(name = "uuid")
    var name: String
)

 

Here we are creating the Employee name dynamically unique id generation by android UUID.

 

Create DAO classes

To communicate Entity and Database we will use DAO classes. Let's create EmployeeDao interface.

package com.rrtutors

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query

@Dao
interface EmployeeDao{
    @Query("SELECT * FROM employeeTbl ORDER BY id DESC")
    fun allEmplyees(): LiveData<List<Emplyee>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(student: Emplyee)
}

 

Update DAO and Entity classes inside Database class, finaly our singleton Database classes will be like below

package com.rrtutors
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import android.content.Context


@Database(entities = arrayOf(Emplyee::class), version = 1, exportSchema = false)
abstract class RoomSingleton : RoomDatabase(){
    abstract fun employeeDao():EmployeeDao

    companion object{
        private var INSTANCE: RoomSingleton? = null
        fun getInstance(context:Context): RoomSingleton{
            if (INSTANCE == null){
                INSTANCE = Room.databaseBuilder(
                    context,
                    RoomSingleton::class.java,
                    "roomdb")
                    .build()
            }

            return INSTANCE as RoomSingleton
        }
    }
}

 

 

Step 4: Create ViewModel and Live Data

In this example we are creating the Employee ViewModel with parameterize constructor. To pass arguments to ViewModel we will use ViewModelFactory pattern.

So create two classes EmployeeViewModel and EmployeeViewModelFactory

 

EmployeeViewModel:

By extend the ViewModel we will create EmployeeViewModel class

class EmployeeViewModel(var application:Application):ViewModel()
{
   
}

 

EmployeeViewModelFactory

package com.rrtutors

import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

class EmployeeViewModelFactory(var application: Application): ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(EmployeeViewModel::class.java)) {
            return EmployeeViewModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }


}

 

Now Let's Add our Database within the ViewModel and add LiveData by fetch the data from database

Finally our EmployeeViewModel class will be like below

package com.rrtutors

import androidx.lifecycle.LiveData
import android.app.Application
import androidx.lifecycle.ViewModel


class EmployeeViewModel(var application:Application):ViewModel()
{
    private val db:RoomSingleton = RoomSingleton.getInstance(application)
    internal val allEmplyees : LiveData<List<Emplyee>> = db.employeeDao().allEmplyees()

    fun insert(student:Emplyee){
        db.employeeDao().insert(student)
    }
}

 

Step 5: Add ViewModel to Activity

Now we need to create ViewModel instance inside Activity and insert employee data to database and fetch data from Database using LiveData reflection

 

In ViewModel we required context, so we will pass this context inside constructor. To create instance of ViewModel with arguments we will use Factory patterns.

So first create instance for EmployeeViewModelFactory, then we will create ViewModel instance

val modelfactory=EmployeeViewModelFactory(application);

        model = ViewModelProvider(this,modelfactory).get(EmployeeViewModel::class.java)

 

To observe the live data changes we will call observe on livedata object

// Observe the model
        model.allEmplyees.observe(this, Observer{ students->
            // Data bind the recycler view
            recyclerView.adapter = RecyclerViewAdapter(students)
        })

 

on tap on button we will insert Employee data into Room database by

btn.setOnClickListener {
           doAsync {
               model.insert(Emplyee(null, UUID.randomUUID().toString()))
           }
       }

 

We know that Room database operations can't run on main thread so we run these operations inside asynchronously. TO do this we used Anko async library.

 Finally our Activity could be like this

package com.rrtutors

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

import org.jetbrains.anko.doAsync
import java.util.*

class MainActivity : AppCompatActivity() {
lateinit var recyclerView:RecyclerView;
lateinit var btn:Button;
    private lateinit var model: EmployeeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        recyclerView=findViewById<RecyclerView>(R.id.recyclerView)
        btn=findViewById<Button>(R.id.btn)
        // Get the view model
        val modelfactory=EmployeeViewModelFactory(application);

        model = ViewModelProvider(this,modelfactory).get(EmployeeViewModel::class.java)

        // Specify layout for recycler view
        val linearLayoutManager = LinearLayoutManager(
            this, RecyclerView.VERTICAL,false)
        recyclerView.layoutManager = linearLayoutManager

        // Observe the model
        model.allEmplyees.observe(this, Observer{ students->
            // Data bind the recycler view
            recyclerView.adapter = RecyclerViewAdapter(students)
        })

        // Insert data into table
        btn.setOnClickListener {
            doAsync {
                model.insert(Emplyee(null, UUID.randomUUID().toString()))
            }
        }
    }
}

 

Conclusion: In this Android Room database tutorial we covered how to work with ViewModel with LiveData and Create ViewModel instance by ViewModelFactory pattern.

 

 

Download Source code

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

621 Views