정상에서 IT를 외치다

[Android Architecture Component] Room 라이브러리 사용하기 본문

안드로이드

[Android Architecture Component] Room 라이브러리 사용하기

Black-Jin 2018. 6. 12. 15:23
반응형

안녕하세요. 블랙진 입니다.


Android Architecture Component 중 Room 라이브러리 사용에 관해 포스팅하겠습니다.


ORM?


Room 를 알아보기 전에 ORM 에 대한 개념을 살펴보겠습니다. ORM이란 Object Relational Mapping 으로 데이터베이스와 객체 지향 프로그래밍 언어간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법으로 DB 테이블과 매핑되는 객체를 만들고 그 객체에서 DB를 관리하는 것입니다.



Room?


안드로이드 아키텍처 컴포넌트 룸 라이브러리는 안드로이드 앱에서 SQLite 데이터베이스를 쉽고 편리하게 사용할 수 있도록 하는 기능입니다. 이를 다시 정리하면 SQLite 위에 만든 구글의 새로운 ORM 이라고 할 수 있습니다. 룸 라이브러리는 엔티티(Entity), 데이터 접근 객체(Data Access Object),  룸 데이터베이스(Room Database),  총 세 개의 구성요소로  나뉩니다.


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


구글 공식사이트 Room


참고 블로그 - java

참고 블로그 - kotlin




How To Use?



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


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


추가) android x 에서의 버전은 여기를 확인해 주세요.

//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>>

...


}

Flowable 형태의 자료를 반환하면 데이터베이스가 변경되면 알림을 받아 새로운 자료를 가져옵니다. 따라서 항상 최신 데이터를 유지하게됩니다.  여기서 재밌는 부분 room 에서의 Flowable 은  complete 를 수행하지 않는다는 것입니다. 이에 대한 질문 및 설명은 링크로 대신 하겠습니다.


Q: The flowable returned by room never completes

A: android developers medium




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> 값입니다.

반응형
Comments