본문 바로가기

Programming/Android_Kotlin

RoomDB에서 LiveData 사용

예전 포스팅에서 Realm이 RoomDB보다 사용이 간편해 Realm을 사용한다고 했는데, 그 중 가장 크게 작용했던 RoomDB의 단점이 Main Thread에서는 사용이 불가능하다는 점이었다.

이전 포스트 👉 Room DB 사용하기

그런데 회사 프로젝트 진행을 하던 중 LiveData를 사용하면 메인 스레드에서도 데이터를 읽어올 수 있다는 글을 보게 되었다.

LiveData 자체가 비동기적으로 동작하기 때문에 Main Thread에서도 에러가 발생하지 않는다는 것이 핵심이었다.

이를 토대로 위 포스트의 코드를 리팩토링 해본다면

@Dao
interface RecipeDao {
	...
	@Query("SELECT * FROM recipe")
	fun getAll(): LiveData<List<Recipe>>
	...
}

위처럼 SELECT문을 LiveData 형태로 받도록 수정해준다.

이제 getAll() 함수의 반환 자료형은 LiveData가 되었기 때문에 Observe가 가능하다!

이를 사용하는 측에서 observe를 해주면 된다.

recipeDB?.recipeDao()?.getAll()?.observe(lifecycleOwner) {
	mAdapter = RecipeAdapter(it)

	recipeRecyclerView.adapter = mAdapter
	recipeRecyclerView.layoutManager = LinearLayoutManager(this)
}

방식으로 라이브데이터의 값을 옵저빙할 수 있게 된다.

이 방식의 장점은 기존의 ViewModel에서 LiveData로 모델을 관리하면서 값의 변화에 따라 뷰를 자동으로 갱신시키는 방식을 그대로 적용할 수가 있다는 것이다!

기존 코드에는 아래처럼 마지막에 갱신된 값을 다시 가져와 뷰를 갱신했다.

Thread {
	val newRecipe = Recipe(
		null,
		itemSpinner.selectedItem.toString(),
		converted,
		convert)
	recipeDB?.recipeDao()?.insert(newRecipe)
	mAdapter.recipes = recipeDB?.recipeDao()?.getAll()!!
}.start()

하지만 이제 뷰를 직접 갱신할 필요가 없다.

lifecycleScope.launch {
	val newRecipe = Recipe(
		null,
		itemSpinner.selectedItem.toString(),
		converted,
		convert)
	recipeDB?.recipeDao()?.insert(newRecipe)
}

위 코드로 DB에 insert를 수행해주면 LiveData에 적용돼있는 Observer가 작동해서 자동으로 뷰를 갱신하게 된다.

RoomDB에 Coroutine을 곁들여 사용하니 정보 흐름이 굉장히 편해지는 느낌이었다.