DEV Community

Cover image for Room Database with Kotlin Flow
Amit Shekhar
Amit Shekhar

Posted on • Edited on • Originally published at outcomeschool.com

Room Database with Kotlin Flow

Hi, I am Amit Shekhar, Co-Founder @ Outcome School • IIT 2010-14 • 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.

In this blog, we will learn how to use Room Database with Kotlin Flow in Android. We will learn to write the code inside the ViewModel with Kotlin Flow that follows a basic MVVM Architecture.

This article was originally published at Outcome School.

I will be using the following project for the implementation part. 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.

GitHub Project: Learn Kotlin Flow

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

implementation "androidx.room:room-runtime:2.4.3"
kapt "androidx.room:room-compiler:2.4.3"
implementation "androidx.room:room-ktx:2.4.3"
Enter fullscreen mode Exit fullscreen mode

Note: Always check for the latest available version.

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

plugins {
    id 'kotlin-kapt'
}
Enter fullscreen mode Exit fullscreen mode

Now, create the entity data class User as below:

@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?
)
Enter fullscreen mode Exit fullscreen mode

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

@Dao
interface UserDao {

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

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

    @Delete
    fun delete(user: User)

}
Enter fullscreen mode Exit fullscreen mode

Now, we need to create a class AppDatabase that extends RoomDatabase.

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

    abstract fun userDao(): UserDao

}
Enter fullscreen mode Exit fullscreen mode

After this, we will be needing a class 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-flow"
        ).build()

}
Enter fullscreen mode Exit fullscreen mode

Then, we will create a DatabaseHelper interface.

interface DatabaseHelper {

    fun getUsers(): Flow<List<User>>

    fun insertAll(users: List<User>): Flow<Unit>

}
Enter fullscreen mode Exit fullscreen mode

After that, we will create a class DatabaseHelperImpl that implements the DatabaseHelper interface.

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

    override fun getUsers(): Flow<List<User>> = flow {
        emit(appDatabase.userDao().getAll())
    }

    override fun insertAll(users: List<User>): Flow<Unit> = flow {
        appDatabase.userDao().insertAll(users)
        emit(Unit)
    }

}
Enter fullscreen mode Exit fullscreen mode

Here, we must understand that the return type is Flow. Also, we are using a flow builder and emitting the item as per the requirement.

Once we've done that, we can create the instance of DatabaseHelper as below:

val dbHelper = DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
Enter fullscreen mode Exit fullscreen mode

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

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

    init {
        fetchUsers()
    }

    private fun fetchUsers() {
        viewModelScope.launch {
            dbHelper.getUsers()
                .flowOn(Dispatchers.IO)
                .catch { e ->
                    // handle exception
                }
                .collect {
                    // list of users from the database
                }
        }
    }

}
Enter fullscreen mode Exit fullscreen mode

This way, we are able to query the database using Kotlin Flow in Android.

This is how we can use Room Database with Kotlin Flow in Android.

That's it for now.

Thanks

Amit Shekhar

Co-Founder @ Outcome School

You can connect with me on:

Read all of our blogs here.

Top comments (0)