Room 사용하기
Android Architecture Component 중 Room
Room? (Database library)
안드로이드 아키텍처 컴포넌트 룸 라이브러리는 안드로이드 앱에서 SQLite 데이터베이스를 쉽고 편리하게 사용할 수 있도록 하는 기능입니다.
룸 라이브러리는 엔티티(Entity), 데이터 접근 객체(Data Access Object), 룸 데이터베이스(Room Database), 총 세 개의 구성요소로 나뉩니다.
그럼 룸 라이브러리를 어떻게 사용하는지 순서대로 설명하겠습니다.
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> 값입니다.