๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

์ฐธ[Android] Room - ๊ธฐ์ดˆ, INSERT์™€ DELETE ์—ฐ์Šต

interfacer_han 2024. 2. 23. 14:52

#1 Room ์†Œ๊ฐœ

 

Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ ์ €์žฅ  |  Android Developers

Room ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด๊ธฐ

developer.android.com

SQLite๋Š” ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ๋ฅผ ์œ„ํ•œ SQL Database ์—”์ง„์ด๋‹ค. SQLite๋Š” ์ˆ˜ ๋งŽ์€ Android ๊ธฐ๊ธฐ์— ํƒ‘์žฌ๋˜์–ด์žˆ๋‹ค. ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด SQLite๋ฅผ ์ž˜ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ, SQLite๋ฅผ ์ƒ์œผ๋กœ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ์‰ฝ์ง€ ์•Š๋‹ค. ๋ฐ˜๋ณต๋˜๋Š” Database Query๋ฌธ ๋“ฑ๊ณผ ๊ฐ™์€ ๋งŽ์€ ์ƒ์šฉ๊ตฌ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ ์–ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ์—, Database ์ž‘์—…์— ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค. ์ด์ƒ์ ์ธ ๊ทธ๋ฆผ์ด ์•„๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๊ตฌ๊ธ€์˜ Room Database persistence ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ถœ์‹œ๋˜์—ˆ๋‹ค. 
 
Room์€ ๊ทธ ์ž์ฒด๊ฐ€ SQLite๋ฅผ ๊ฐ์‹ธ๋Š” ์ถ”์ƒํ™” ๊ณ„์ธต์ด๋‹ค. ๊ทธ๋ ‡๊ฒŒ, SQLite์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋งค๋„๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค. Room์€ SQLite ์‚ฌ์šฉ ์ ˆ์ฐจ์˜ ๋งŽ์€ ๋ถ€๋ถ„์„ ์•”์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ธฐ์—, ์ฝ”๋“œ๋Ÿ‰์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
 
Room์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ž…๋ ฅํ•œ Annotation์„ ์ธ์‹ํ•˜์—ฌ ๋™์ž‘ํ•œ๋‹ค. Anonotation์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋™์ž‘์ด ์•”์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค. Room์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” 3๊ฐ€์ง€ ํด๋ž˜์Šค๊ฐ€ ์ด์šฉ๋œ๋‹ค. ์ฒซ์งธ๋Š”, Database์˜ ํ…Œ์ด๋ธ”์„ ๋Œ€๋ณ€ํ•˜๋Š” Entity ํด๋ž˜์Šค. Annotation์€ @Entity๋‹ค. ๋‘˜์งธ๋Š”, Database์— ์ ‘๊ทผํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” DAO(Database Access Object Interface) ํด๋ž˜์Šค. Annotation์€ @Dao๋‹ค. ์…‹์งธ๋Š”, ์‹ค์ œ SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋Œ€๋ณ€ํ•˜๋Š” Database ํด๋ž˜์Šค. Annotation์€ @Database๋‹ค. 
 

#2 Room์˜ ๊ธฐ๋ณธ์„ ๋‹ด์€ ์ƒ˜ํ”Œ ์•ฑ ๊ฐœ์š”

 

[Android] MVVM ๊ตฌ์กฐ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

#1 ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์˜ '์ „ํ†ต์ ์ธ' ๋ฐฉ์‹ vs MVVM ํŒจํ„ด #1-1 ๋„์‹๋„์™€ ์ข…์†์„ฑ ํ™”์‚ดํ‘œ๋Š” ํด๋ž˜์Šค ๊ฐ„์˜ ์ข…์†์„ฑ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, View๋Š” ViewModel์— ์ข…์†๋œ๋‹ค. ์ข…์†์˜ ์‚ฌ์ „์  ์˜๋ฏธ๋Š” '์ž์ฃผ์„ฑ์ด ์—†์ด ์ฃผ๊ฐ€

kenel.tistory.com

์œ„ ๊ฒŒ์‹œ๊ธ€์˜ #1-3๊ณผ ๊ฐ™์€ MVVM ํŒจํ„ด ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๋Š” ์ƒ˜ํ”Œ ์•ฑ์„ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค. ์œ„ ๊ฒŒ์‹œ๊ธ€์˜ #1-3 ์šฐ์ธก ํ•˜๋‹จ์— ์žˆ๋Š” Remote Data Source ๋ถ€๋ถ„์€ ๋ณธ ์ƒ˜ํ”Œ์—์„œ๋Š” ์ œ์™ธํ•œ๋‹ค.
 

#3 ์ƒ˜ํ”Œ ์•ฑ ์ œ์ž‘ - ์™„์„ฑ๋œ ์•ฑ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

์™„์„ฑ๋œ ์•ฑ์˜ ์Šคํฌ๋ฆฐ์ƒท์„ ๊ฐ€์ ธ์™”๋‹ค. ์œ„์™€ ๊ฐ™์€ ๋ชจ์Šต์ด ๋˜๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค. ์•„๋žซ ๋ถ€๋ถ„์— ์žˆ๋Š” RecyclerView์˜ Item์„ ํด๋ฆญํ•˜๋ฉด ๋ฒ„ํŠผ์˜ Text์™€ ๊ธฐ๋Šฅ์ด ๋ฐ”๋€Œ๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.

#4 ์ƒ˜ํ”Œ ์•ฑ ์ œ์ž‘ - build.gradle.kts (Module) ์ˆ˜์ •ํ•˜๊ธฐ

plugins {
    ...
    // kapt (Annotation ์ฝ๊ธฐ)
    id("kotlin-kapt")
}

android {
    ...
    // Data binding
    buildFeatures {
        dataBinding = true
    }
}

dependencies {
    ...
    
    val lifecycleVersion = "2.7.0"
    val roomVersion = "2.6.1"
    val coroutinesVersion = "1.7.3"

    // ViewModel
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion")
    
    // LiveData
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion")
    implementation ("androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion")
    
    // Room
    implementation ("androidx.room:room-runtime:$roomVersion")
    implementation ("androidx.room:room-ktx:$roomVersion") // ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” Optional์ด๋ผ๊ณ  ๋˜์–ด ์žˆ๋‹ค. ์„ค๋ช… ์ฐธ์กฐ.
    
    // kapt (Annotation ์ฝ๊ธฐ)
    kapt ("androidx.room:room-compiler:$roomVersion")

    //Coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")
}

Data binding, ViewModel, LiveData, Coroutines ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ถ”๊ฐ€๋กœ, Annotation ๊ตฌ๋ฌธ์„ ์ฝ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ kotlin-kapt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ๋„ฃ๋Š”๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ, Room ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์ถ”๊ฐ€ํ•œ๋‹ค. room-runtime์€ ํ•„์ˆ˜๊ณ , room-ktx๋Š” ์„ ํƒ์ (Optional)์œผ๋กœ implementationํ•˜๋ผ๊ณ  ๊ณต์‹๋ฌธ์„œ์— ๋‚˜์™€ ์žˆ๋‹ค. room-ktx๋Š” Room์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Coroutines ํด๋ž˜์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค. Room์„ Background ์Šค๋ ˆ๋“œ์—์„œ ๋Œ๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ, Coroutines์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค.
 

#5 ์ƒ˜ํ”Œ ์•ฑ ์ œ์ž‘ - Entity, DAO, Database, Repository ํด๋ž˜์Šค ๊ตฌํ˜„

#5-1 Entity, DAO, Database

 

[Android] Room - Entity, DAO, Database

#1 ์ด์ „ ๊ธ€ https://kenel.tistory.com/120 ๋ณธ ๊ฒŒ์‹œ๊ธ€์€ Room์˜ ๊ธฐ๋ณธ์„ ๋‹ด์€ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ด์ „ ๊ฒŒ์‹œ๊ธ€์—์„œ ์ด์–ด์ง„๋‹ค. ์—ฌ๊ธฐ์„œ Room์˜ 3๊ฐ€์ง€ ํ•ต์‹ฌ ํด๋ž˜์Šค์ธ Entity ํด๋ž˜์Šค, DAO ํด๋ž˜์Šค, Database ํด๋ž˜์Šค์˜ ๊ตฌํ˜„

kenel.tistory.com

Model์— ํ•ด๋‹นํ•˜๋Š”, Room์˜ 3๊ฐ€์ง€ ํ•ต์‹ฌ ํด๋ž˜์Šค์ธ Entity ํด๋ž˜์Šค, DAO ํด๋ž˜์Šค, Database ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. Room์˜ ํ•ต์‹ฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ ๊ฒŒ์‹œ๊ธ€๋กœ ๋บ๋‹ค.
 

#5-2 Repository (UserRepository.kt)

// package com.example.roombasics.db

class UserRepository(private val dao: UserDAO) {

    val users = dao.getAllUsers()

    suspend fun insert(user: User) {
        dao.insertUser(user)
    }

    suspend fun update(user: User) {
        dao.updateUser(user)
    }

    suspend fun delete(user: User) {
        dao.deleteUser(user)
    }

    suspend fun deleteAll() {
        dao.deleteAll()
    }
}

Repository ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— DAO๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„ฃ๋Š”๋‹ค. Repository์—์„œ DAO์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ˜ธ์ถœํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dao.getAllUsers()๋Š” suspend ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์ง€ ์•Š์€ ํ•จ์ˆ˜์ด๊ธฐ์— ๊ทธ return๊ฐ’์„ users๋ผ๋Š” ํ”„๋กœํผํ‹ฐ์— ๋‹ด์•˜๋‹ค. suspend ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜๋ผ๋ฉด ๋ถˆ๊ฐ€๋Šฅํ–ˆ์„ ๊ฒƒ์ด๋‹ค. (์—ฌ๊ธฐ ์ฐธ์กฐ. ์—ฌ๋‹ด์œผ๋กœ, ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์—์„œ ๋งŒ๋“  insertUser2() ๋“ฑ์€ ์ผ๋ถ€๋Ÿฌ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜๋‹ค.)
 

#6 ์ƒ˜ํ”Œ ์•ฑ ์ œ์ž‘ - Repository, ViewModel, Activity, Data Binding ๊ตฌํ˜„

 

[Android] MVVM ๊ตฌ์กฐ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

#1 ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์˜ '์ „ํ†ต์ ์ธ' ๋ฐฉ์‹ vs MVVM ํŒจํ„ด ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์—์„œ๋Š” Activity๊ฐ€ UI ๋กœ์ง(ํ™”๋ฉด ํ‘œ์‹œ ๋ฐ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ ์ฒ˜๋ฆฌ)๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ, ๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ ๋“ฑ)์„ ๋ชจ๋‘ ๋‹ด๋‹นํ–ˆ๋‹ค. ๋”ฐ

kenel.tistory.com

์œ„ ๊ฒŒ์‹œ๊ธ€์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ MVVM ํŒจํ„ด์„ ์™„์„ฑํ•œ๋‹ค.
 

๋”๋ณด๊ธฐ

#6-1 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="12sp"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/name_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="12sp"
            android:ems="10"
            android:hint="Name"
            android:inputType="text" />

        <EditText
            android:id="@+id/email_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="12sp"
            android:ems="10"
            android:hint="E-mail"
            android:inputType="text" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="12sp"
            android:orientation="horizontal">

            <Button
                android:id="@+id/save_or_update_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="12sp" />

            <Button
                android:id="@+id/clear_all_or_delete_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/user_recycler"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</layout>

๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ, ์„ ์ œ์ ์œผ๋กœ ์ „์ฒด ์ฝ”๋“œ๋ฅผ <layout> ํƒœ๊ทธ๋กœ ๊ฐ์ŒŒ๋‹ค.

 

#6-2 ViewModel (UserViewModel.kt)

// package com.example.roombasics

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.roombasics.db.User
import com.example.roombasics.db.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class UserViewModel(private val repository: UserRepository) : ViewModel() {

    val users = repository.users // ํ˜„์žฌ ์ €์žฅ๋œ User๋“ค
    val inputtedUser = MutableLiveData<User>() // View์˜ ์ž…๋ ฅ ๋ฐ•์Šค์™€ ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ์ฒด

    private var isUpdateOrDelete = false
    val saveOrUpdateButtonText = MutableLiveData<String>()
    val clearAllOrDeleteButtonText = MutableLiveData<String>()

    init {
        initSaveAndClearAll()
    }

    // ์ดˆ๊ธฐํ™” ๊ด€๋ จ
    fun initSaveAndClearAll() {
        clearInputBox()
        renewButtonText()
    }

    fun initUpdateAndDelete(user: User) {
        TODO()
    }

    // ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋™์ž‘
    fun saveOrUpdate() {
        if (isUpdateOrDelete) {
            // Update ์ž‘์—…
            TODO()
        } else {
            // Save ์ž‘์—…
            insert(inputtedUser.value!!)
            clearInputBox()
        }
    }

    fun clearAllOrDelete() {
        if (isUpdateOrDelete) {
            // Delete ์ž‘์—…
            TODO()
        } else {
            // Clear All ์ž‘์—…
            clearAll()
        }
    }

    // Repository ๋™์ž‘๊ณผ ๊ด€๋ จ๋œ ๋ฉ”์†Œ๋“œ๋“ค
    fun insert(user: User) = viewModelScope.launch(Dispatchers.IO) {
        repository.insert(user)
    }

    fun update(user: User) = viewModelScope.launch(Dispatchers.IO) {
        TODO()
    }

    fun delete(user: User) = viewModelScope.launch(Dispatchers.IO) {
        TODO()
    }

    fun clearAll() = viewModelScope.launch(Dispatchers.IO) {
        repository.deleteAll()
    }

    // ๊ธฐํƒ€ UI ๋‹ค๋“ฌ๊ธฐ์šฉ ๋ฉ”์†Œ๋“œ๋“ค
    private fun clearInputBox() {
        inputtedUser.value = User(0, "", "")
    }

    private fun renewButtonText() {
        if (isUpdateOrDelete) {
            saveOrUpdateButtonText.value = "Update"
            clearAllOrDeleteButtonText.value = "Delete"
        } else {
            saveOrUpdateButtonText.value = "Save"
            clearAllOrDeleteButtonText.value = "Clear All"
        }
    }
}

ViewModel ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— Repository๋ฅผ ๋„ฃ๋Š”๋‹ค. Repository๋Š” ViewModel๊ณผ DAO๋ฅผ ์ž‡๋Š” ์ง•๊ฒ€๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋ฏธ ์ €์žฅ๋œ User ๊ฐ์ฒด์˜ List์ธ users ํ”„๋กœํผํ‹ฐ์™€ View์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ž…๋ ฅ๋˜๋Š” ์ •๋ณด๋ฅผ ๋”ฐ๋ฅด๋Š” MutableLiveData<Users>()ํ˜• inputtedUser๊ฐ€ ์„œ๋กœ ๊ตฌ๋ถ„๋˜์–ด ํ”„๋กœํผํ‹ฐ๋กœ ์กด์žฌํ•œ๋‹ค. 2๊ฐœ์˜ ๋ฒ„ํŠผ์€ ๊ฐ๊ฐ 2๊ฐ€์ง€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ Text๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ๊ทธ ์ƒํ™ฉ์€ isUpdateOrDelete์˜ true or false๋กœ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ƒํ™ฉ์˜ ์ „ํ™˜์€ initSaveAndUpdate() ํ•จ์ˆ˜ ๋˜๋Š” initUpdateAndDelete() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ง„ํ–‰ํ•œ๋‹ค. ๊ณณ๊ณณ์— ์žˆ๋Š” TODO()๋Š” ์ด์–ด์ง€๋Š” ๊ฒŒ์‹œ๊ธ€์—์„œ ๊ตฌํ˜„ํ•œ๋‹ค.

 

#6-3 ViewModelFactory (UserViewModelFactory.kt)

// package com.example.roombasics

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.roombasics.db.UserRepository

class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
            return UserViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel Class")
    }
}

#6-2์˜ ViewModel์€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋ฏ€๋กœ, ViewModelFactory๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

#6-4 ๋‹ค์‹œ activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="userViewModel"
            type="com.example.roombasics.UserViewModel" />
    </data>

    <LinearLayout ...>

        <EditText
            android:id="@+id/name_text"
            ...
            android:text="@={userViewModel.inputtedUser.name}" />

        <EditText
            android:id="@+id/email_text"
            ...
            android:text="@={userViewModel.inputtedUser.email}" />

        <LinearLayout ...>

            <Button
                android:id="@+id/save_or_update_button"
                ...
                android:onClick="@{() -> userViewModel.saveOrUpdate()}"
                android:text="@={userViewModel.saveOrUpdateButtonText}" />

            <Button
                android:id="@+id/clear_all_or_delete_button"
                ...
                android:onClick="@{() -> userViewModel.clearAllOrDelete()}"
                android:text="@={userViewModel.clearAllOrDeleteButtonText}" />
        </LinearLayout>

        <androidx.recyclerview.widget.RecyclerView .../>
    </LinearLayout>
</layout>

ViewModel์„ View(activity_main.xml)์—์„œ ๋ฐ›์•„ ์‚ฌ์šฉ(๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ)ํ•˜๊ธฐ ์œ„ํ•ด์„œ #6-1์˜ ์ฝ”๋“œ๋ฅผ ์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค.

 

#6-5 Activity (MainActivity.kt)

// package com.example.roombasics

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.roombasics.databinding.ActivityMainBinding
import com.example.roombasics.db.UserDatabase
import com.example.roombasics.db.UserRepository

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        val dao = UserDatabase.getInstance(application).userDAO
        val repository = UserRepository(dao)
        val factory = UserViewModelFactory(repository)
        userViewModel = ViewModelProvider(this, factory)[UserViewModel::class.java]

        binding.userViewModel = userViewModel
        binding.lifecycleOwner = this

        displayUsersList()
    }

    private fun displayUsersList() {
        userViewModel.users.observe(this, Observer {
            Log.i("interfacer_han", it.toString())
        })
    }
}

DAO ์ธ์Šคํ„ด์Šค๋กœ Repository ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค. ๋งŒ๋“  Repository ์ธ์Šคํ„ด์Šค๋กœ ViewModelFactory ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ViewModelFactory ์ธ์Šคํ„ด์Šค๋กœ ViewModel ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค. ViewModel ์ธ์Šคํ„ด์Šค๋ฅผ activity_main.xml๊ณผ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉํ•˜๊ณ , LiveData์˜ ๋™์ž‘์„ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๊ฐ์ฒด์— LifecycleOwner๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” Activity ์ž๊ธฐ ์ž์‹ ๋„ ๋„˜๊ฒจ์ค€๋‹ค. ViewModel์˜ LiveDataํ˜• ํ”„๋กœํผํ‹ฐ์ธ Users๋ฅผ LiveData.observe()ํ•˜์—ฌ ๊ทธ ๋ณ€๋™์‚ฌํ•ญ์„ Log ๋ฉ”์‹œ์ง€๋กœ ํ‘œ์‹œํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

 

#7 ์ž‘๋™ ํ™•์ธ

RecyclerView์˜ ๊ตฌํ˜„์ด ๋‚จ์•˜์ง€๋งŒ, ์ง€๊ธˆ๊นŒ์ง€ ์™„์„ฑํ•œ ์•ฑ์˜ ์ž‘๋™์„ ํ™•์ธํ•ด๋ณธ๋‹ค.
 

#7-1 ์Šคํฌ๋ฆฐ์ƒท

 

#7-2 Log ๋ฉ”์‹œ์ง€

1. ์ดˆ๊ธฐํ™”๋ฉด []
2. ์ฒซ๋ฒˆ์งธ User ์ž…๋ ฅ ํ›„ Save ๋ฒ„ํŠผ ํด๋ฆญ [User(id=1, name=Gildong Hong, email=gildong@example.com)]
3. ๋‘๋ฒˆ์งธ User ์ž…๋ ฅ ํ›„ Save ๋ฒ„ํŠผ ํด๋ฆญ [User(id=1, name=Gildong Hong, email=gildong@example.com), User(id=2, name=Taewon Han, email=interfacerHan@example.com)]
4. Clear All ๋ฒ„ํŠผ ํด๋ฆญ []

 

#8 ์š”์•ฝ

Room์€ SQLite์˜ ์„ธ๋ จ๋œ ์‚ฌ์šฉ์ด๋‹ค.

#9 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/room/RoomBasics at master · Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com

 

#10 ์ด์–ด์ง€๋Š” ๊ธ€

 

[Android] Room - UPDATE ์—ฐ์Šต

#1 ์ด์ „ ๊ธ€ [Android] Room - ๊ธฐ์ดˆ, INSERT์™€ DELETE ์—ฐ์Šต #1 Room ์†Œ๊ฐœ Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ ์ €์žฅ | Android Developers Room ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด

kenel.tistory.com

์ด์–ด์ง€๋Š” ๊ธ€์—์„œ, ๊ฐ Entity๊ฐ€ ํ•˜๋‚˜์˜ Item์œผ๋กœ์„œ ๋‹ด๊ฒจ์žˆ๋Š” RecyclerView๊นŒ์ง€ ๊ตฌํ˜„ํ•ด๋ณธ๋‹ค. ์—ฌ๊ธฐ์—, RecyclerView์˜ Item์„ ํด๋ฆญํ•˜์—ฌ ํ•ด๋‹น Item์— ๋‹ด๊ธด Entity์„ UPDATEํ•  ์ˆ˜๋„ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.