데이터베이스를 지금 사용하지 않더라도 data 패키지에 인터페이스를 만드시고 Fake DB를 구현하셔서 작업하는 걸 권장드려요. 일반적으로 데이터베이스에 필요한 데이터 구조와 View에 필요한 데이터구조가 달라지기 때문에, 이걸 나중에 하려고 미루면 코드의 수정이 아주 많아 질 수도 있습니다. Fake DB에 어떤 데이터베이스에서 사용할 데이터 타입을 두고 Map 같은 걸 사용해서 데이터를 리턴해주는 식으로 간단하게 구현하면 됩니다.
interface Entity<ID> {
val id: String
}
data class BodyPartEntity(
override val Id: String,
val name: String,
): Entity<String>
interface Dao<ID, T> {
fun getList(): T
fun getOne(id: ID): T?
fun save(id:ID, data: T)
fun delete(id: ID)
}
class BodyPartDao: Dao<String, BodyPartEntity> {
private val storage = hashMapOf<String, BodyPartEntity>)()
override fun getList(): T = storage.values().toList()
override fun getOne(id: String): T? = storage.getOrNull(id)
fun save(id:ID, data: T){
storage[id] = data
}
fun delete(id: ID) {
stroage.delete[id]
}
}
object DatabaseFactory {
val bodyPartDao: Dao<String, BodyPartEntity> by lazy {
BodyPartDao()
}
}
이런 식으로 만드셔서 ViewModel 에서는 interface를 가져다 사용하세요.
val bodyPartDao: Dao<String, BodyPartEntity> get() = DaoFactory.bodyPartDao
추후에 데이터베이스를 추가힐 때는 인터페이스는 그대로 두시고 실제 Database 를 이용한 구현 클래스를 하나 만드시면 되겠죠.
이래야 수정사항이ㅣ 적어집니다. 단위테스트도 가능해 지구요.
그리고 아래코드는 약간의 수정이 필요합니다.
class WorkoutListViewModel(private val resources: Resources)
ViewModel에는 라이프사이클 옵저버같은 라이프사이클 관련 코드외에는 안드로이드 플랫폼을 참조하면 안됩니다. ViewModel 은 단위테스트가 가능하도록 설계가 되었기때문에 안드로이드 플랫폼에 대한 참조를 가능한 가지지 말아야 합니다.
class WorkoutListViewModel(private val workoutListSource: WorkoutListSource) : ViewModel(){
}
위처럼, WorkoutListSource 를 바로 Inject 하세요.
그리고 LiveData를 observe할 때는
viewModel.part.observe(viewLifecycleOwner) { _ ->
adapter.addItems(viewModel.getList())
....
}
ViewModel 에서 postValue할 때 View에 필요한 데이터도 같이 전달하세요.
sealed class WorkoutListViewState {
data class BodyPart(val selectedPart: String): WorkoutListViewState()
data class BodyParts(val parts: List<String>): WorkoutListViewState()
}
class WorkoutListViewModel(private val resources: Resources) : ViewModel(){
private var _part :MutableLiveData<BodyPart> = MutableLiveData()
private var _list : MutableLiveData<BodyParts> = MutableLiveData(arrayListOf())
}
viewModel.part.observe(view.lifecycleOwner, ::updateUi)
fun updateUi(viewState: WorkoutListViewState) {
when (viewState) {
is WorkoutListViewState.BodyPart -> updateBodyPart(viewState)
is WorkoutListViewState.BodyParts -> updateBodyParts(viewState)
}
}
fun updateBodyPart(WorkoutListViewState.BodyPart) {
}
fun updateBodyParts(WorkoutListViewState.BodyParts {
}
뷰에서는 가능하면 ViewModel이 주는 데이터를 가져다 그대로 사용할 수 있는 Passive View로 만들어 주시는 게 좋습니다.