개발/최적화

뷰모델 중복 이슈 해결

이도일 2023. 5. 3. 17:00

https://medium.com/prnd/mvvm의-viewmodel에서-이벤트를-처리하는-방법-6가지-31bb183a88ce

뷰모델의 문제점

  • 뷰모델은 뷰가 변경되면 가장 최근 값들로 .observe를 해주는데 , 중요한건 이게 값이 바뀌지 않아도 최근 값을 걍 들고오기때문에…..
  • 토스트를 띄운 후 나갔다가 다시 fragment 갱신 → 토스트 재생성과 같은 중복 이슈가 발생하게 된다.

 

 

해결 방안

  • 사실 이 문제는 아주 흔한 것이라서 구글에서 이미 해결책을 내놨다.
  • 나는 SharedFlow + Sealed class + Lifecycle 를 사용했다.

 

 

SharedFlow

private val _eventflow = MutableSharedFlow<Resource<Event>>()
    val eventflow: MutableSharedFlow<Resource<Event>> = _eventflow

 

Event emit

private fun event(event: Resource<Event>) {
        launchViewModelScope {
            _eventflow.emit(event)
        }
    }

 

Event Data Class

sealed class Event {
        data class deleteTimeTable (val value: BaseServiceModel) : Event()
        data class getTimeTableList (val value: TimeTable) : Event()
        data class getTimeTableInfo (val value: TimeTableInfo) : Event()
        data class getSubjectList (val value: TimeTableSubject) : Event()
        data class insertSubjectByOne (val value: BaseServiceModel) : Event()
        data class deleteSubject (val value: BaseServiceModel) : Event()
        data class saveTimeTableInfo2( val value: BaseServiceModel) : Event()
    }

 

Handle Event func (in Activity)

private fun handleEvent(event: Resource<Event>) {
        when (event.status) {
            Status.LOADING -> {
                ProgressUtil.progressOn(requireActivity())
            }
            Status.SUCCESS -> {
                ProgressUtil.progressOff()
                when (event.data) {
                    is Event.getTimeTableList -> {
                        event.data.value?.let { data ->
                            titleArrayList.clear()
                            setSelectedPosition = 0
                            if (data.List.isNotEmpty()) {
                                binding.frameLayout.visibility = View.VISIBLE
                                binding.topLayout.visibility = View.VISIBLE
                                binding.subjectLayout.visibility = View.VISIBLE
                                binding.emptyText.visibility = View.GONE

                                data.List.forEach { tableData ->
                                    titleArrayList.add(tableData.TTM_Title)
                                }

                                if (titleArrayList.size == 1) {
                                    binding.spinner.visibility = View.GONE
                                    binding.calArrow.visibility = View.GONE
                                } else {
                                    binding.spinner.visibility = View.VISIBLE
                                    binding.calArrow.visibility = View.VISIBLE
                                }
//                            Dlog.d("timetable titleArrayList = $titleArrayList")
//                            binding.timeTableTitle.text = titleArrayList[setSelectedPosition]
                                timeTableMasSeq = data.List[setSelectedPosition].TTM_SEQ
                                viewModel.getSubjectList()
                                //viewModel.getTimeTableInfo(data.List[0].TTM_SEQ)
                                spdSeq = SharedPreference.getTimetableSpdSeqPref(requireContext())
//                            Dlog.d("timetable spdSeq = $spdSeq changeTimeTable")
                                if (spdSeq != "0") {
                                    binding.timeTableTitle.postDelayed({
                                        getFromData()
                                    }, 300)
                                } else {
                                    binding.timeTableTitle.text =
                                        titleArrayList[setSelectedPosition]
                                }
                                if (binding.timeTableRecyclerview.visibility == View.INVISIBLE) {
                                    binding.timeTableTitle.postDelayed({
                                        binding.timeTableRecyclerview.visibility = View.VISIBLE
                                        binding.loading.visibility = View.GONE
                                    }, 750)
                                }
                            } else {
                                binding.frameLayout.visibility = View.GONE
                                binding.topLayout.visibility = View.GONE
                                binding.subjectLayout.visibility = View.GONE
                                binding.emptyText.visibility = View.VISIBLE
//                            binding.timeTableRecyclerview.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
                                binding.timeTableRecyclerview.visibility = View.VISIBLE
                                binding.loading.visibility = View.GONE
                            }
                            spinnerAdapter.setItem(titleArrayList)
                            spinnerAdapter.setSelectedPosition(setSelectedPosition)
                            spinnerAdapter.notifyDataSetChanged()
                        }
                    }
                    is Event.deleteTimeTable -> {
                        event.data.value?.let { data ->
                            if (data.SuccessYN == ResultCode.RESULT_YES) {
                                viewModel.getTimeTableList()
                                ToastUtil.showShort(data.Message)
                            }
                        }
                    }
                    is Event.insertSubjectByOne -> {
                        event.data.value?.let { data ->
                            ToastUtil.showShort(data.Message)
                            if (data.SuccessYN == ResultCode.RESULT_YES) {
                                dialogAddSubject.dismiss()
                                viewModel.getSubjectList()
                            }
                        }
                    }
                    is Event.deleteSubject -> {
                        ProgressUtil.progressOff()
                        event.data.value?.let { data ->
                            if (data.SuccessYN == ResultCode.RESULT_YES) {
                                ToastUtil.showShort(data.Message)
                                dialogEditSubject.dismiss()
                                viewModel.getTimeTableInfo(timeTableMasSeq)
                            }
                        }
                    }
                    is Event.getTimeTableInfo -> {
                        event.data.value.let {
                            it
                            //viewModel.getSubjectList()
                            setTimeTable(it)
                        }
                    }
                    is Event.getSubjectList -> {
                        event.data?.value.List?.let { data ->
                            setSubject(data as ArrayList<TimeTableSubjectData>)
                            viewModel.getTimeTableInfo(timeTableMasSeq)
                        }
                    }
                    is Event.saveTimeTableInfo2 -> {
                        event.data?.value.let { data ->
                            if (data.SuccessYN == ResultCode.RESULT_YES) {
                                ToastUtil.showShort(data.Message)
                                viewModel.getTimeTableInfo(timeTableMasSeq)
                            }
                        }
                    }
                }
            }
            Status.ERROR -> {

            }
        }
    }

 

Collect(in Activity)

repeatOnStarted {
            viewModel.eventflow.collect { event -> handleEvent(event) }
        }