마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

동적 리사이클러뷰와 mvvm 패턴

0 추천
버튼을 누르면 아이템을 추가하는 리사이클러뷰를 만들고있는데요.

요기다가 mvvm 패턴을 적용하려니 어떻게 해야할지 감이 잘안오네요.

그냥 리사이클러뷰에대한 깃 코드는 좀 있어도 저처럼 동적리사이클러뷰에관한

mvvm 코드는 잘없는것같아서..

리사이클러뷰 아이템을 동적으로 만든다면 아이템을 추가삭제를 해야하는데요.

뷰모델에 그리고 뷰모델의 라이브데이터에 아이템을 만들고 데이터를 세팅시키고 추가하는방법은

바람직한 방법인가요?그리고 가능할까요?

리사이클러뷰의 DiffUtil이 아이템을 명확히 업데이트 하는 역할을하는데,

과연 뷰모델을 사용해서 아이템을 추가삭제해도 되나요? 만약 이게가능하다면

diffutil의 존재 의미가 많이 없어지지않나요?
codeslave (3,940 포인트) 님이 2021년 7월 11일 질문

1개의 답변

0 추천

관련코드는 Github에 넘쳐납니다. 저도 가끔은 참고를 하니까요.

MVVM에서 ViewModel의 역할은 Model를 통해서 가져온 데이터를 View가 화면에 그려주기 쉽도록  가공해서 뷰에 전달해 주는 겁니다. 따라서 RecyclerView Adapter에 필요한 데이터는 ViewModel로 부터 제공이 되어야 하고 Adapter에 데이터가 추가되어야 한다면 ViewModel에 있는 데이터 소스에 먼저 반영이 되고 이 결과가 View로 전달이 되어야 합니다 즉, 데이터 흐름의 방향은
View -> ViewModel -> Model, Model -> ViewModel -> View 의 한 방향이 됩니다.

그리고 DiffUtil이 역할은 RecyclerView를 효율적으로 업데이트 하기 위해 존재하는 겁니다. 실제 변경이 된 아이템만 다시 그려줄 수 있도록 말이죠. 이걸 ViewModel쪽에 두자면 그럴 수도 있을 겁니다 .하지만 제 생각으로는 ViewModel보다는 View쪽에서 처리하는 것이 덜 복잡해진다고 생각해요. ViewModel에서 너무 많은 일을 할 필요는 없습니다.

대략적으로 아래처럼 코드가 흘러갈겁니다.

// View
viewModel.itemsLiveData.observe(viewLifeCycleObserver) { items ->
       adapter.submitList(item)
}

addButton.setOnClickListener {
     viewModel.addItemClicked(item)
}


// ViewModel
private val useCase: AddItemUseCase

fun addItemClicked(item: Item) {
   viewMoelScope.launch {
         val result = useCase.addItem(item)
         if (!result.isSuccess) {
             return@launch errorLiveData.postValue(result.error)
         } 
        
         val items = useCase.getItems() 
          itemsLiveData.postValue( items.toAdapterItems())
    }
}

 

spark (227,510 포인트) 님이 2021년 7월 11일 답변
감사합니다. 선생님 adapter를 생성 및 초기화 하고 adapter에 아이템을 추가하는것은 ViewModel 내에서 진행되어야할까요 아니면 뷰(액티비티, 프래그먼트)에서 진행되어야 할까요? Adapter는 뷰라기보다는 데이터(모델)쪽에 가까운것 같은데..
샘플 코드를 몇개 참고해서 보고 있는데.. 어떤분은 뷰모델의 프로퍼티로 어댑터를 생성하시고 어댑터에 this를 전달해서 어댑터 내에서 아예 뷰모델로 하시고,,
(https://hwanine.github.io/android/MVVMFinal/#newsadapterkt)


어떤분은 평범하게 뷰에서 어댑터를 초기화하고 observer 뷰모델을 관찰해서 하시더라구요..
(https://gwynn.tistory.com/59)


어떤게 MVVM 패턴에 더 부합한가요?

뷰모델을
MVx(MVC, MVP, MVVM, MVI) 패턴의 중요한 원칙 중의 하나는 Controller, Presenter, ViewModel에는 LiveData같은 ViewModel에서 LiveCycle을 지원을 위해 만들어진 클래스 말고는 안드로이드 플랫폼과 관련된 참조를 하면 안된다는 것입니다. 예를 들면 Context가 대표적이죠. RecyclerView.Adapter도 마찬가지구요. 더군다나 RecyclerView.Adapter는 크클래스 이름이 말해주듯이 뷰쪽의 클래스입니다. 주된 이유는 플랫폼 클래스들을 참조하게 되면 Unit테스트가 안된다는 거구요. 디자인 패턴의 구조상 어떤 플랫폼에 종속적인 코드가 가능하면 포함되지 않는 것이 좋습니다. 그래야 독립적인 코드가 가능합니다.
ViewModel에 필요한 것은 RecyclerView.Adapter에서 사용하는 데이터 뿐입니다.
링크 중 첫번째는 MVVM 패턴을 잘못 이해한 예로 보여집니다. 말씀드렸다시피 RecyclerView.Adapter는 ViewModel에서 참조하면 안됩니다. 두번째는 흔히 작성하게 되는코드이구요. 첫번째 예처럼 쓰기 시작하면 MVVM에서 레이어의 경계가 무너집니다. 굳이 MVVM을 쓸 이유가 없어요.
위에서 말씀드렸듯이 Unit test가 문제가 되는 것이 첫번째 이유이고, 화면에서 사용하던 Adapter에 Item과 관련해서 Listener를 달거나 변경해야 한다고 하면, 첫번째 예제에서는 어떻게 접근해야 할까요? 해당 기능의 지원을 위해 ViewModel을 건드려야하는 이상한 상황이 생깁니다. 그리고 RecyclerView.adapter는 메모리누수 방지를 위해 마지막에는 null로 세팅해주는 것이 좋은데, 이건 어떻게 처리할까요? 등등등..
편하게는 보이지만 제 생각으로는 바람직한 디자인은 아니라고 보여지네요.
...