Android room 사용법 및 설정 방법 (viewModel & repository)

1. Gradle 설정

plugins {
    id 'kotlin-kapt'  // 추가하기
}

dependencies {
    // Room DB
    def room_version = "2.6.1"
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
}



2. repository & dao & model 만들기

@Entity
data class JobSite(
    @PrimaryKey(autoGenerate = true) val uid: Int,
    @ColumnInfo(name = "companyName") var companyName: String?,
    @ColumnInfo(name = "companyUrl") var companyUrl: String?
) {
    constructor(companyName: String?, companyUrl: String?) : this(0, companyName, companyUrl)
}



@Dao
interface JobSiteDao {

    @Query("SELECT * FROM JobSite")
    fun getAll(): Flow<List<JobSite>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(jobSite: JobSite)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(vararg jobSites: JobSite)

    @Delete
    fun delete(jobSite: JobSite)
}



class JobSiteRepository(private val jobSiteDao: JobSiteDao) {

    val allJobSites: Flow<List<JobSite>> = jobSiteDao.getAll()

    @WorkerThread
    suspend fun insert(jobSite: JobSite) {
        jobSiteDao.insert(jobSite)
    }

    @WorkerThread
    suspend fun update(jobSite: JobSite) {
        jobSiteDao.update(jobSite)
    }

    @WorkerThread
    suspend fun delete(jobSite: JobSite) {
        jobSiteDao.delete(jobSite)
    }
}



3. AppDataBase 파일 만들기

@Database(entities = [JobSite::class], version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun jobSiteDao(): JobSiteDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getInstance(
            context: Context,
            scope: CoroutineScope
        ): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "word_database"
                )
                    // Wipes and rebuilds instead of migrating if no Migration object.
                    // Migration is not part of this codelab.
                    .fallbackToDestructiveMigration()
                    .addCallback(JobSiteDatabaseCallback(scope))
                    .build()
                INSTANCE = instance
                // return instance
                instance
            }
        }
    }

    private class JobSiteDatabaseCallback(
        private val scope: CoroutineScope
    ) : RoomDatabase.Callback() {
        /**
         * Override the onCreate method to populate the database.
         */
        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)
            // If you want to keep the data through app restarts,
            // comment out the following line.
            INSTANCE?.let { database ->
                scope.launch(Dispatchers.IO) {
                    Log.e(javaClass.simpleName, "DB 성공 이후 데이터 초기화")

                    val jobSites = mutableListOf<JobSite>().apply {
                        add(JobSite(companyName = "삼성", companyUrl = "https://www.samsungcareers.com/hr/"))
                    }.toTypedArray()

                    val dao = database.jobSiteDao()
                    dao.insertAll(*jobSites)
                }
            }
        }
    }
}



4. Application & ViewModel 설정

class JobSiteApplication: Application() {

    private val applicationScope = CoroutineScope(SupervisorJob())

    private val database by lazy { AppDatabase.getInstance(applicationContext, applicationScope)}

    val jobSiteRepository by lazy { JobSiteRepository(database.jobSiteDao()) }
}

// AndroidManifest.xml
<application
    android:name=".JobSiteApplication" />



class ListViewModel(private val repository: JobSiteRepository) : ViewModel() {

    val jobSites: LiveData<List<JobSite>> = repository.allJobSites.asLiveData()

    fun insert(jobSite: JobSite) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.insert(jobSite)
        }
    }

    fun update(jobSite: JobSite) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.update(jobSite)
        }
    }

    fun delete(jobSite: JobSite) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.delete(jobSite)
        }
    }
}

class MyViewModelFactory(private val repository: JobSiteRepository) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(ListViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return ListViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}



5. UI 에서 room 호출

class ListFragment : Fragment() {
    
    // 뷰모델 선언
    private val listViewModel: ListViewModel by viewModels { MyViewModelFactory((requireActivity().application as JobSiteApplication).jobSiteRepository) }
    
    // LiveData 관찰
    private fun initObserveLiveData() {
        listViewModel.jobSites.observe(viewLifecycleOwner) { jobSites ->
            // your logic
        }
    }
}

결론



Related Posts