본문 바로가기
개발/Android

[Android] Adapter에서 ViewModel 사용하기

by tempus 2022. 3. 30.
반응형

개인 프로젝트를 하던 중, 리스트의 아이템을 삭제하고 변경 사항을 Room에 저장하기 위해 ViewModel을 사용해야 했다. 처음에는 ViewModel의 인스턴스를 adpater 생성 시에 같이 넘겨주려고 생각을 했었다.

하지만 찾아보니 Adapter가 ViewModel의 인스턴스를 가지고 있다면 ViewModel 생명 주기가 더 길기 때문에 메모리 해제가 안 될 수 있기 때문에 웬만하면 adapter에는 표시해줄 데이터만 넘겨주어야겠다는 생각이 들었다.

 

그래서 callback 함수를 구현해서 이벤트를 넘겨주기로 했다. 이전에 커스텀 다이얼로그를 만들 때 구현해봐서 어렵지 않게 구현할 수 있었다.

 

준비물은 다음과 같다. (내 실제 코드의 일부분이다. 불필요한 부분들은 모두 삭제했다.)

 

Listener를 위한 인터페이스를 작성해준다.

interface OnItemClick {
    fun deleteToDo(item : FoodEntity)
}

 

ViewModel도 같이 준비해준다.

@HiltViewModel
class FoodViewModel @Inject constructor(
    private val repository: FoodRepository
) : ViewModel()
{
    private val foodAllData : LiveData<List<FoodEntity>> = repository.getAll()

    fun delete(item : FoodEntity){
        viewModelScope.launch {
            repository.deleteFood(item)
        }
    }
}

 

Adapter에 onItemClick을 인스턴스로 받고 클릭 시 리스너를 등록해준다.

class FoodAdapter(listener : OnItemClick) :  ListAdapter<FoodEntity, RecyclerView.ViewHolder>(FoodDiffCallback()) {

    private val mCallback = listener

    inner class ViewHolder(private val binding : FoodItemBinding) : RecyclerView.ViewHolder(binding.root){
        fun bind(data : FoodEntity) {

            binding.tags.text = data.getTagList()
            binding.title.text = data.name
            binding.deleteBtn.visibility = if(data.isCustom) View.VISIBLE else View.GONE

            binding.deleteBtn.setOnClickListener {
                mCallback.deleteToDo(data)
            }
        }
    }

    
}

 

Fragment에서는 다음과 같이 작성해준다.Fragment에서 OnItemclick을 implements 하고 ViewModel을 사용해준다.

class MenuManagementFragment : BaseFragment<FragmentMenuManagementBinding>(FragmentMenuManagementBinding::inflate) ,OnItemClick {
   
    private val foodViewModel by activityViewModels<FoodViewModel>()
    private val adapter = FoodAdapter(this)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        super.onViewCreated(view, savedInstanceState)
 
        foodViewModel.getAll().observe(viewLifecycleOwner) { foods ->
            adapter.submitList(foods)
        }
    }

    override fun deleteToDo(item: FoodEntity) {
        foodViewModel.delete(item)
    }

}

이렇게 작성하면 아이템의 삭제 버튼을 누를 시 해당 아이템은 삭제되고 ViewModel에 접근하여 삭제된 내용은 Room에 적용이 된다.

 

더 좋은 방법이 있다면 댓글로 남겨주세요!

 

반응형

댓글


loading