-
Room 은 SQLite 의 추상화 layer 를 제공하는 lib 으로, SQLite 의 모든 기능을 사용하면서 더 견고한 db 접근을 할 수 있게 해준다.
-
Room 이 많은 부분을 케어해주기 때문에, SQLite 대신에 Room 을 사용하는 것이 강추된다.
-
Room 에는 3가지 컴퍼넌트가 있다.
1. Database
DB holder 를 가지고 있으며, 앱의 relational 한 영구적인 data 에 접근하는 채널이 된다.
@Database 로 annotate 된 class 는 다음 조건을 충족시켜야 한다.
RoomDatabase 를 상속하는 abstract class 가 되도록 한다.
db 에 들어갈 entity 들을 annotation 으로 정의해준다.
@Dao 로 annotate 된 class 를 return 하는 argument 가 없는 abstract method 를 가져야 한다.
Runtime 에 Room.databaseBuilder() 또는 Room.inMemoryDatabaseBuilder() 를 통해 DB instance 를 얻을 수 있다.
2. Entity
DB 안의 Table 을 정의한다.
3. DAO
DB 를 접근하는 method 들을 가진다.
-
데이터에 접근하기 위해서는 Room 를 통해서 DAO 를 가져오고, 그 DAO 를 통해 데이터에 접근한다.
Declaring dependencies
-
Google Maven repo 가 필요하다.
Room 에 대한 dependency 는 Room migration testing 과 Room RxJava 를 포함한다.
-
dependencies{
def room_version = "2.2.6" // version 은 알아서
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// kotlin 은 annotationProcessor 대신 kapt 를 사용한다.
// kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin extensions and Coroutine support for Room
implementation "androidx.room:room-ktx:$room_version"
// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - Test helpers
testImplementation "androidx.room:room-testing$room_version"
}
-
kotlin 기반 앱은 annotationProcessor 대신 kapt 를 사용하도록 해야 한다.
이를 위해서 kotlin-kapt plugin 을 추가해야 한다.
( kapt 는 Kotlin Annotation Processing Tool 의 약자 )
-
@Entity
data class User(
@PrimaryKey
val uid: Int,
@ColumnInfo(name = "first_name")
val firstName: String:?,
@ColumnInfo(name = "last_name")
val lastName:String?
)
@Dao
interface UserDao{
@Query("SELECT * FROM user")
fun getAll(): List<User>
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun loadAllByIds(userIds:IntArray): List<User>
@Query("SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1")
fun findByName(first:String, last:String): User
@Insert
fun insertAll(vararg users:User)
@Delete
fun delete(user:User)
}
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase: RoomDatabase(){
abstract fun userDao(): UserDao
}
-
val db = Room.databaseBuilder(appContext, AppDatabase::class.java, "database-name")
.build()
-
앱이 single process 로 동작한다면, AppDatabase object 를 만들 때 singleton design pattern 을 따르는 것이 좋다.
각각의 RoomDatabase instance 는 생성하는 데 상당히 많은 비용이 들고, multiple instance 를 만들 이유가 거의 없다.
만약 multiple process 로 동작한다면, database builder 를 만들 때 enableMultiInstanceInvalidation() 을 호출해주는 것이 좋다.
이렇게 하면 AppDatabase 는 각각의 process 에 하나씩 instance 를 갖게 되고, shared db file 을 invalidate 하게 되면, 이 invalidation 은 자동으로 다른 process 의 AppDatabase instance 에 전파된다.
-
참고 자료
https://developer.android.com/jetpack/androidx/releases/room
https://developer.android.com/training/data-storage/room/index.html
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[android] Define data using entities - Room 에 대해 알아보자 (0) | 2020.08.19 |
---|---|
[android] Accessing data using Room DAOs - Room 에 대해 알아보자 (0) | 2020.08.18 |
[android] dpi 값이 바뀔 수 있구나?!! ㄷㄷㄷ (0) | 2020.08.15 |
[android] 앱 업데이트시 다운로드 사이즈 줄이기 (0) | 2020.08.14 |
[android] Activity Task 에 대한 이야기 with allowTaskReparenting 실험 (심화) (0) | 2020.08.13 |
댓글