본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] Room 에 대해 알아보자 - 기초

by 돼지왕왕돼지 2020. 8. 17.


android room tutorial

https://developer.android.com/jetpack/androidx/releases/room

https://developer.android.com/training/data-storage/room/index.html


-

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 를 통해 데이터에 접근한다.


android room structure




Declaring dependencies


-

Google Maven repo 가 필요하다.

Room 에 대한 dependency 는 Room migration testing 과 Room RxJava 를 포함한다.



-

dependencies{

    def room_version = “2.1.0-rc01” // version 은 알아서

    

    implementation “androidx.room:room-runtime:$room_version”

    annotationProcessor “androidx.room:room-compiler:$room_version” // kotlin 은 annotationProcessor 대신 kapt 를 사용한다.

    

    // 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 에 전파된다.




-

끝!!!




댓글0