I am Amit Shekhar, a mentor helping developers in getting high-paying tech jobs.
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 amitshekhar.me.
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"
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'
}
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?
)
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)
}
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
}
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()
}
Then, we will create a DatabaseHelper
interface.
interface DatabaseHelper {
fun getUsers(): Flow<List<User>>
fun insertAll(users: List<User>): Flow<Unit>
}
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)
}
}
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))
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
}
}
}
}
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
You can connect with me on: