Skip to content

RoomDB

ViewModel Required - add kapt plugin at plugins section

plugins {
id("kotlin-kapt")
}
implementation("androidx.room:room-ktx:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
@Entity(tableName = "user")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val name: String, // default column name will be "name"
// Set some custom props with @ColumnInfo like custom ColumnName or DefaultValue
@ColumnInfo(name = "user_name", defaultValue = "Unknown", collate = ColumnInfo.NOCASE) val name: String = "EliasChen",
val age: Int,
val hobby: String
)

To set the default value: val name: String = "EliasChen"

@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Query("SELECT * FROM user")
suspend fun getAllUsers(): List<User>
// use flow to auto get updated data
@Query("SELECT * FROM user")
fun getAllUsers(): Flow<List<User>>
@Delete
suspend fun delete(user: User)
@Query("DELETE FROM user")
suspend fun deleteAll()
@Query("SELECT COUNT(*) FROM user WHERE name = :name")
suspend fun checkNameExists(name: String): Int
}

Parse fun’s data to @Query by adding : at the start of the string. Ex: :name

@Database(entities = [<Schema-name>::class,<Schema-name>::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

Requires passing context from parent

fun getDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(
context.applicationContext, AppDatabase::class.java, "app_database"
)
.fallbackToDestructiveMigration()
.build()
}

Use .fallbackToDestructiveMigration() to drop old schema when DB migrates

context.deleteDatabase("db")
class TodoViewModel(private val db: AppDB) : ViewModel() {
val allTodo: Flow<List<Todo>> = db.todoDao().select()
fun insert(todo: Todo) = viewModelScope.launch {
db.todoDao().insert(todo)
}
fun deleteTodo(id: Int) = viewModelScope.launch {
db.todoDao().delete(id)
}
fun updateName(newName: String, id: Int) = viewModelScope.launch {
db.todoDao().updateName(newName, id)
}
fun updateDone(done: Boolean, id: Int) = viewModelScope.launch {
db.todoDao().doneTodo(done, id)
}
}
class UserViewModel(private val database: AppDatabase) : ViewModel() {
val users = mutableStateListOf<User>() // for storing data from DB
init {
updateUsers()
}
fun updateUsers() {
viewModelScope.launch {
users.clear()
users.addAll(database.userDao().getAllUsers())
}
}
fun addUser(name: String) {
viewModelScope.launch {
database.userDao().insert(User(name = name))
updateUsers()
}
}
fun deleteUser(user: User) {
viewModelScope.launch {
database.userDao().delete(user)
updateUsers()
}
}
fun deleteAllUsers() {
viewModelScope.launch {
database.userDao().deleteAll()
updateUsers()
}
}
suspend fun checkNameExists(name: String): Boolean {
return database.userDao().checkNameExists(name) > 0
}
}

NOTE: All DB actions must be in a suspend function or a viewModelScope

val database = getDatabase(this)
val userViewModel = UserViewModel(database)

Create database from MainActivity and pass database to the viewModel that interacts with the database