Room Database with Kotlin Coroutines

Authors
  • Amit Shekhar
    Name
    Amit Shekhar
    Published on
Room Database with Kotlin Coroutines

I am Amit Shekhar, I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.

Join my program and get high paying tech job: amitshekhar.me

Before we start, I would like to mention that, I have released a video playlist to help you crack the Android Interview: Check out Android Interview Questions and Answers.

In this blog, we will learn how to use Room Database with Kotlin Coroutines.

I will be using this project for the implementation part. If you have not gone through the project, you should go through it and then come back. The project follows a basic MVVM Architecture for simplicity. You can find the complete code for the implementation mentioned in this blog in the project itself.

First, we need to set up our dependencies for the Room Database like below:

implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"

Do not forget to add the Kotlin plugin for Annotation Processing in your app-level gradle file.

apply plugin: 'kotlin-kapt'

Now, create the entity which will be our data class required for Room Database, for example, User.

@Entity
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "name") val name: String?,
    @ColumnInfo(name = "email") val email: String?,
    @ColumnInfo(name = "avatar") val avatar: String?
)

For this User, we need to create Dao required for Room Database, which we will name as UserDao.

@Dao
interface UserDao {

    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Insert
    suspend fun insertAll(users: List<User>)

    @Delete
    suspend fun delete(user: User)

}

Note: We have used suspend keyword to support Coroutines so that we can call it from a Coroutine or another suspend function.

Now, we need to create the AppDatabase which will extend RoomDatabase.

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

}

After this, we will be needing a DatabaseBuilder which will be a Singleton.

object DatabaseBuilder {

    private var INSTANCE: AppDatabase? = null

    fun getInstance(context: Context): AppDatabase {
        if (INSTANCE == null) {
            synchronized(AppDatabase::class) {
                if (INSTANCE == null) {
                    INSTANCE = buildRoomDB(context)
                }
            }
        }
        return INSTANCE!!
    }

    private fun buildRoomDB(context: Context) =
        Room.databaseBuilder(
            context.applicationContext,
            AppDatabase::class.java,
            "learn-kotlin-coroutines"
        ).build()

}

Then, we will create a DatabaseHelper interface.

interface DatabaseHelper {

    suspend fun getUsers(): List<User>

    suspend fun insertAll(users: List<User>)

}

Then, we will create a DatabaseHelperImpl which will implement the DatabaseHelper.

class DatabaseHelperImpl(private val appDatabase: AppDatabase) : DatabaseHelper {

    override suspend fun getUsers(): List<User> = appDatabase.userDao().getAll()

    override suspend fun insertAll(users: List<User>) = appDatabase.userDao().insertAll(users)

}

Note: Again, we have used the suspend so that we can call it from a coroutine or another suspend function.

Then, we can create the instance of DatabaseHelper like below:

val dbHelper = DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))

We can pass this instance wherever required, for example to the ViewModel and make the query to get the users from the database like below:

class RoomDBViewModel(private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper) :
    ViewModel() {

    init {
        fetchUsers()
    }

    private fun fetchUsers() {
        viewModelScope.launch {
            try {
                val usersFromDb = dbHelper.getUsers()

                // here you have your usersFromDb

            } catch (e: Exception) {
                // handle error
            }
        }
    }

}

This way, we are able to query the database using Kotlin Coroutines.

You can find the end-to-end implementation in this project.

Prepare yourself for Android Interview: Android Interview Questions

That's it for now.

Thanks

Amit Shekhar

You can connect with me on:

Read all of my high-quality blogs here.