android

Room 사용하기

junmong 2020. 3. 10. 00:06

Android Architecture Component 중 Room

 

Room? (Database library)

안드로이드 아키텍처 컴포넌트 룸 라이브러리는 안드로이드 앱에서 SQLite 데이터베이스를 쉽고 편리하게 사용할 수 있도록 하는 기능입니다.

룸 라이브러리는 엔티티(Entity), 데이터 접근 객체(Data Access Object),  룸 데이터베이스(Room Database),  총 세 개의 구성요소로  나뉩니다.

그럼 룸 라이브러리를 어떻게 사용하는지 순서대로 설명하겠습니다.

 

구글 공식사이트 Room

참고 블로그 - java

참고 블로그 - kotlin

 

How To Use?

 

 

1.  build.gradle 파일의 dependencies 에 추가해 줍니다.

 

제가 사용한 roomVersion = 1.1.0 입니다. 최신 버전은 Room 여기서 확인해 주세요.

 

//room

implementation "android.arch.persistence.room:runtime:$roomVersion"

kapt "android.arch.persistence.room:compiler:$roomVersion"

 

 

 

2. 엔티티(Entity)를 만들어 줍니다.

 

엔티티는 데이터베이스에 저장할 데이터의 형식을 정의합니다.

 

저는 Person 데이터를 만들어서 이름(name) 과 직업(job) 변수를 갖는 객체를 만들었습니다.

 

@Entity

class Person(

        @PrimaryKey val id: Int,

        val name: String,

        val job: String)

 

적어도 한개의 PrimaryKey 가 반드시 있어야 합니다.

 

저는 id 값을 PrimaryKey 로 만들었으며 변수 타입은 Int 로 하였습니다.

 

 

 

 

3. 데이터 접극 객체(Date Access Object)를 생성합니다.

 

데이터 접근 객체는 데이터베이스를 통해 수행할 작업을 정의한 클래스 입니다.  데이터의 삽입, 수정, 삭제 작업이나 저장된 데이터를 불러오는 작업 등을 함수 형태로 정의 합니다.

 

@Dao

interface PersonDao {

 

    @Query("SELECT * FROM person")

    fun getAllPerson(): List<Person>

 

    @Query("DELETE FROM person")

    fun clearAll()

 

    //해당 데이터를 추가합니다.

    @Insert

    fun insert(vararg person: Person)

 

    //헤당 데이터를 업데이트 합니다.

    @Update

    fun update(vararg person: Person)

 

    //해당 데이터를 삭제합니다.

    @Delete

    fun delete(vararg person: Person)

}

 

데이터를 추가 할 때 같은 primary key 값을 가진 객체를 추가하면 에러가 발생합니다.

이미 저장된 항목이 있을 경우 데이터를 덮어 씌우는 방법이 있습니다.

//이미 저장된 항목이 있을 경우 데이터를 덮어씁니다.

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun insert(vararg person: Person)

위와 같이 onConflict 를 추가해 주면 동일 항목의 경우 자동으로 데이터를 덮어씌웁니다.

 

4. 룸 데이터베이스(Room Database)를 생성합니다.

 

룸 데이터베이스에서 데이터베이스를 생성하거나 버전을 관리합니다.

 

 

@Database(entities = arrayOf(Person::class), version = 1)

abstract class PersonDatabase: RoomDatabase() {

 

    abstract fun getPersonDao(): PersonDao

 

    companion object {

 

        private var INSTANCE: PersonDatabase? = null

 

        fun getInstance(context: Context): PersonDatabase? {

 

            if(INSTANCE == null) {

                synchronized(PersonDatabase::class) {

                    INSTANCE = Room.databaseBuilder(

                            context,

                            PersonDatabase::class.java,

                            "person.db")

                            .build()

                }

            }

            return INSTANCE

        }

    }

}

 

 

5. 데이터 삽입과 불러오기

 

데이터 삽입과 불러오기 등 데이터를 처리하는 작업은 모두 Background Thread 에서 처리해야 합니다.

 

데이터 삽입

val person = Person(0, "blackJin","Developer")

 

PersonDatabase

        .getInstance(context)!!

        .getPersonDao()

        .insert(person)

 

데이터 불러오기

val items = PersonDatabase

        .getInstance(context)!!

        .getPersonDao()

        .getAllPerson()

 

 

 

 

Using RxJava in Room

 

Room의 데이터는 모두 백그라운드 쓰레드에서 처리해야 합니다.

 

백그라운드 쓰레드에서 사용할 수 있는 강력한 도구가 바로 RxJava 입니다. 

 

 

1.  build.gradle 파일의 dependencies 에 추가해 줍니다.

Room 라이브러리에 Rx 를 적용할 수 있게 해줍니다.

implementation "android.arch.persistence.room:rxjava2:$roomVersion"

Android Studio 에서 Rx 를 사용할 수 있게 해줍니다.

현재 기준 rxAndroidVersion = '2.0.2' , rxJavaVersion = '2.1.3'

implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"

implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"

 

 

2.  PersonDao 에서 데이터를 받는 getAllPerson 의 반환값을 Flowable 로 변경합니다.

 

@Dao

interface PersonDao {

 

    ...

 

    @Query("SELECT * FROM person")

    fun getAllPersonRx(): Flowable<List<Person>>

 

   ...

 

}

 

 

3.  데이터를 받고 처리할 화면에서 아래 코드를 사용하시면 됩니다.

 

데이터 삽입

 

val person = Person(0 ,"blackJin","Developer")

 

Observable.just(person)

        .subscribeOn(Schedulers.io())

        .subscribe( {

 

            PersonDatabase

                    .getInstance(context)!!

                    .getPersonDao()

                    .insert(person)

 

 

        }, {

 

            Log.e("MyTag", it.message)

 

        })

 

Observable 를 사용하여 백그라운드 쓰레드에서 데이터를 처리합니다.

 

위에서 Person 의 PrimaryKey 값을 0 으로 설정해 주었는데 데이터를 추가 해 줄때마다 이 PrimaryKey 를 높여주기 불편할 수 있습니다.

 

이에 자동으로 PrimaryKey 를 증가시켜 줄 수 있는데요

 

@Entity

class Person(

        @PrimaryKey(autoGenerate = true)

        val id: Int,

        val name: String,

        val job: String)

 

위와 같이 설정하면 자동으로 PrimaryKey 가 증가합니다.

 

 

 

데이터 불러오기

 

PersonDatabase

        .getInstance(context)!!

        .getPersonDao()

        .getAllPersonRx()

        .observeOn(AndroidSchedulers.mainThread())

        .doOnSubscribe { // 구독시 사용할 함수 }

        .doOnTerminate { // 구독이 끝날 때 사용할 함수 }

        .subscribe( {

 

            adapter.setItem(it.toMutableList())

 

       

        }, {

 

            Log.e("MyTag", it.message)

 

        }))

 

위와 같이 사용하시면 되겠습니다. subscribe 에서의 it 값이 List<Person> 값입니다.