Mobile Application Development - Part 9a

Using SQLite and Room with ViewModel and LiveData

This extension to Topic 9 explains how you can efficiently use SQLite and Room with ViewModel and LiveData.

Updating a Room DAO to return LiveData

It's easy to update a DAO to return LiveData.We simply update our DAO so that the search methods return LiveData of the appropriate type. So, in a student records app, we might change:

@Query("SELECT * FROM students")
fun getAllStudents(): List<Student>
to:
@Query("SELECT * FROM students")
fun getAllStudents(): LiveData<List<Student>>
This allows other parts of your code to observe changes in the database and auto-update as the database updates.

Using LiveData and a ViewModel with Room

The other thing we can do is to use both LiveData and a ViewModel together with Room. To do this you would return LiveData from the DAO (as above) and store a reference to it in your ViewModel. Then, you can observe the data in the ViewModel with an Observer, as before.

Here is an example of a ViewModel set up to store LiveData from a Room database containing student records:

package com.example.roomapp

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

// We need to pass in the Application object
class StudentViewModel(app: Application): AndroidViewModel(app)  {
    // Get a reference to the database, using the Application object
    var db = StudentDatabase.getDatabase(app)
    var students : LiveData<List<Student>>

    // When we initialise the ViewModel, get the LiveData from the DAO
    // The variable 'students' will always contain the latest LiveData.
    init {
        students = db.studentDao().getAllStudents()
    }

    // Return the LiveData, so it can be observed, e.g. from the MainActivity
    fun getAllStudents(): LiveData<List<Student>> {
        return students
    }
}
The ViewModel would then be setup from the MainActivity in the normal way:
val viewModel : StudentViewModel by viewModels()
and observed in the normal way by observing the getAllStudents() method of the ViewModel:
viewModel.getAllStudents().observe(this, Observer {
    stateResults = it.joinToString("\n") // display data in 'stateResults', a state variable 
})