Android

[안드로이드] Room 라이브러리를 사용해보자

남드로이드 2022. 1. 9. 22:17

Room이란?

:Room은 SQLite에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하는 동시에 SQLite를 완벽히 활용합니다.

용도

가장 일반적인 사용 사례는 관련 데이터를 캐싱하는 것입니다.이런 방식으로 기기가 네트워크에 액세스할 수 없을 때 오프라인 상태인 동안에도 사용자가 여전히 콘텐츠를 탐색할 수 있습니다.

구성요소

데이터베이스
: 데이터베이스 홀더를 포함하며 앱의 지속적인 관계형 데이터의 기본 연결을 위한 기본 액세스 포인트 역할을 합니다.
엔티티
: 데이터베이스 내의 테이블을 나타냅니다.
DAO
: 데이터베이스에 액세스하는 데 사용되는 메서드가 포함되어 있습니다.

장단점??

Room 아키텍쳐 다이어그램

* 사용예제

간단하게 고객테이블을 하나 설계하고 조회/저장 기능을 만들어보고자 한다.

레이아웃

레이아웃

 

기능설명

조회: 아이디입력 -> 이름/휴대폰번호/주소 조회

저장: 아이디/이름/휴대폰번호/주소 저장

 

dependency 추가

dependencies {
    implementation 'androidx.room:room-runtime:2.3.0'
    kapt 'androidx.room:room-compiler:2.3.0'
}

kotlin -plugin 추가

plugins {
    id 'kotlin-kapt'
}

테이블 엔티티를 만들어준다

@Entity
data class CustomerEntity(
    @PrimaryKey @ColumnInfo(name = "id") val id: String,
    @ColumnInfo(name = "name") val name: String,
    @ColumnInfo(name = "phone number") val phone: String,
    @ColumnInfo(name = "address") val address:String
)

DAO 인터페이스를 만들어준다

DAO??

@Dao
interface CustomerDao {
    @Query("SELECT * FROM CustomerEntity")
    fun getAll(): List<CustomerEntity>
    @Query("SELECT * FROM CustomerEntity WHERE name = :name")
    fun getRowByName(name:String):CustomerEntity
    @Insert
    fun insertAll(customerEntity:CustomerEntity)
}

데이터베이스 추상클래스를 만들어준다

@Database(entities = [CustomerEntity::class], version = 1)
abstract class CustomerDatabase: RoomDatabase() {
    abstract fun customerDao(): CustomerDao

    // SINGLETON
    companion object { // 클래스 설계도에 붙어있는 객체. static, 클래스변수와 비슷함
        private var instance: CustomerDatabase? = null

        fun getInstance(context: Context):CustomerDatabase?{
            if(instance == null){
                // 객체접근 동기화
                synchronized(CustomerDatabase::class){
                    instance = Room.databaseBuilder(context,
                            CustomerDatabase::class.java,
                            "CustomerEntity")
                            // .allowMainThreadQueries() // UI Thread 에서 접근가능
                            .build()
                }
            }
            return instance
        }
    }
}

메인액티비티에서 데이터베이스 인스턴스를 만들어준다

var db:CustomerDatabase? = CustomerDatabase.getInstance(this)

db의 접근은 UI스레드에서 할수없으므로 백그라운드에서 처리한다.

왜???

비동기 처리를 위해서 사용가능한 방법들 (코루틴/rxkotlin/asynctesk/thread)
코루틴이 필요하니 써보자
dependency

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")

인스턴스를 통해 DAO를 호출한다

// 조회
        btnInquiry.setOnClickListener {
            // TODO: 2021-12-02 쿼리처리 동기회 + 백그라운드처리
            // TODO: 2021-12-03 코루틴을 사용해보자

            var customerEntity:CustomerEntity? = null
            // TODO: 2021-12-03 DB와 뷰 사이의 동기화가 어렵다. ViewModel로 디자인을 변경해보자
            GlobalScope.launch {
                customerEntity = db!!.customerDao().getRowByid(customerId.text.toString())// !!: Null 이 들어올 수 없음.
                delay(500L)
                runOnUiThread{
                    if(customerEntity != null){
                        customerId.setText(customerEntity!!.id)
                        customerName.setText(customerEntity!!.name)
                        customerPhone.setText(customerEntity!!.phone)
                        customerAddress.setText(customerEntity!!.address)
                        Toast.makeText(context, "Inquiry", Toast.LENGTH_SHORT).show()
                    }
                    else{
                        Toast.makeText(context, "No data", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }
// 저장
        btnSave.setOnClickListener {
            var customerEntity:CustomerEntity = CustomerEntity(customerId.text.toString(), customerName.text.toString(), customerPhone.text.toString(), customerAddress.text.toString())
            GlobalScope.launch {
                db!!.customerDao().insertAll(customerEntity)
            }
            Toast.makeText(this, "save", Toast.LENGTH_SHORT).show()
        }

 

트러블슈팅

1. 엔티티 변경시 발생
Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
=> 앱을 삭제 후에 재설치

 

조회후 화면
DB Inspector

 

모르는것

1. 코루틴 동기화

db인서트 이후 응답을 받아 nrm or err 처리를 해야함.

 

 

참고
https://developer.android.com/training/data-storage/room

전체소스
https://github.com/njs8590/RoomExample