hilt적용하는 프로젝트에 room 사용하기
gradle 설정하기
//build.gradle(Project) buildscript { dependencies { classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha' } } ㅤ //build.gradle(Module) ㅤ //plugin에 //id 'kotlin-kapt' //id 'kotlin-android-extensions' //id 'dagger.hilt.android.plugin' //넣기 ㅤ //room def roomVersion = "2.4.1" implementation "androidx.room:room-runtime:$roomVersion" // To use Kotlin annotation processing tool (kapt) kapt "androidx.room:room-compiler:$roomVersion" ㅤ //코루틴 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9") ㅤ //hilt implementation "com.google.dagger:hilt-android:2.28-alpha" kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
Myapplication.class
@HiltAndroidApp class MyApplication : Application() {}
Manifest.xml
//application 에 name 지정<application android:name=".MyApplication"/>
Entitiy
@Entity @Parcelize //직렬화의 한 방법. Parcelize 어노테이션을 쓰면 알아서 직렬화가 된다. data class User( @PrimaryKey(autoGenerate = true) var id: Int = 0, var name: String, var age: String, var phone: String ㅤㅤ //@SerializedName("color") //val color: String //json 으로 받은 데이터 중 키 값이 color인 데이터가 바로 여기에 들어간다. //따라서 json 키 값과 SerializedName값이 동일 해야함 //gson 어노테이션임 ) : Parcelable
DAO
@Dao interface UserDao { // @Insert // fun insert(user: User) ㅤ @Update suspend fun update(user: User) ❗️room은 main thread에서 작업하면 에러가 납니다. 따라서 꼭 suspend 함수로 진행하길!!! ㅤ // @Delete // fun delete(user: User) ㅤ @Query("SELECT * FROM User") suspend fun selectUser(): List<User> ㅤ @Query("SELECT * FROM User WHERE id = :id") suspend fun selectUser(id: String): User? ㅤ @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(entity: User) ㅤ @Query("DELETE FROM User WHERE id = :id") suspend fun deleteUser(id: String) ㅤ // OnConflictStrategy.ABORT 충돌이 발생할 경우 처리 중단 // OnConflictStrategy.FAIL 충돌이 발생할 경우 실패처리 // OnConflictStrategy.IGNORE 충돌이 발생할 경우 무시 // OnConflictStrategy.REPLACE 충돌이 발생할 경우 덮어쓰기 // OnConflictStrategy.ROLLBACK 충돌이 발생할 경우 이전으로 되돌리기 }
DataBase
@Database( entities = [ User::class ], version = 1 ) //companion object로 싱글톤 db 만들어서 바로 불러서 썼던 것과 다르게, //hilt에서는 추상클래스와 추상메소드로 만들고 module에서 구현해 준다음 //실제 사용하는 곳에서는 inject 해서 사용한다. abstract class UserDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
DataBaseModule
@InstallIn(ApplicationComponent::class) //액티비티가 혹은 프래그먼트가 살아있는 동안에는 같은 hilt 인스턴스을 쓰겠다. 를 지정해주는 곳 //ApplicationComponent 는 singleton 범위로써, application이 생성되고 죽을때까지 계속 똑같은 hilt 인스턴스를 반환한다. //리소스가 많이 소비되기 때문에 db를 싱글톤으로 만들으라는 room 규칙에 들어맞음. @Module // (UserDataBase) 추상 클래스는 바로 inject 해서 쓸 수 없다. hilt가 추상 클래스가 어디에 구현되어 있는지 모르기 때문 //따라서 Module을 만들어서 구현해야 hilt가 구현부를 찾아 갈 수 있다. //hilt야 UserDatabase 여기 모듈에 구현되어있어 라고 말하는 너낌 class DatabaseModule { @Provides //Moudle을 구현하는 방법에는 Provides와 Bidns 두가지가 있다. 외부라이브러리에는 Binds를 못쓴다. @Singleton //module을 싱글톤으로 만들겠다. fun provideAppDatabase(@ApplicationContext context: Context) = Room.databaseBuilder( context, UserDatabase::class.java, "user_db" ).fallbackToDestructiveMigration() .build() ㅤ @Provides fun provideUserDao(appDatabase: UserDatabase) = appDatabase.userDao() }
MainActivity.class
//@AndroidEntryPoint 어노테이션으로 hilt에게 dependency 주입 받을 거라고 알려준다. lateinit var userDatabase: UserDatabase var newUser = User(name = "20", age = "13", phone = "010-1111-5556") lifecycleScope.launch { userDatabase.userDao().insert(newUser) }