본문 바로가기

토이프로젝트/todolist

todolist - 체크 기능 추가

 

 

데이터는 Room을 사용하여 저장하였고, 등록하는 기능과 삭제하는 기능은 간단했다.

그런데 리사이클러뷰로 만들어진 뷰에 선택한 데이터만 삭제하려고 하니 걱정이 생겼다.

지금까지 Room을 통해서 데이터를 수정하기 위해선 viewModel이 필요했다.

// MainActivity에서 버튼을 클릭하면 뷰모델을 통해 데이터를 삭제하는 기능
binding.button.setOnClickListner {
    viewModel.deleteAllToDoList()
}

 

그런데 리사이클러뷰에는 viewModel 객체가 없다. viewModel 객체를 생성자로 넘길까도 생각했지만 좋지 않은 패턴 같아서 그만뒀다.
Can I pass the ViewModel to a RecyclerView Adapter and observe a LiveData?
View models for RecyclerView items

 

View models for RecyclerView items

My activity has a Google's ViewModel that fetches some model items. These items are then transformed into adapter items of a RecyclerView. There are also many types of adapter items supported by one

stackoverflow.com

 

Can I pass the ViewModel to a RecyclerView Adapter and observe a LiveData?

I'm started to implement MVVM and I do not know if use the ViewModel inside my Adapter is a Good Practice or an AntiPattern. To give you an example, think about a list of colors and an Image that ...

stackoverflow.com

 

 

그래서 찾아낸 방법이 고차함수로 Adapter에 db관련 메서드를 넘기는 것이었다.

package com.goodee.todolist

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LiveData
import androidx.recyclerview.widget.RecyclerView
import com.goodee.todolist.database.ToDoList
import com.goodee.todolist.databinding.ItemTodolistBinding

class ToDoListAdapter(var toDoLists: LiveData<List<ToDoList>>,
                      private val doneTodoList: ((Int) -> Unit)?    // 얘를 이용함
                      ):
    RecyclerView.Adapter<ToDoListAdapter.ViewHolder>() {
    private val TAG: String = "로그"

    inner class ViewHolder(binding: ItemTodolistBinding) : RecyclerView.ViewHolder(binding.root) {
        val primaryKey = binding.textviewItemPrimarykey
        val title = binding.textviewItemTitle
        val content = binding.textviewItemContent
        val isFinish = binding.checkboxItemIsfinish
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoListAdapter.ViewHolder {
        val binding = DataBindingUtil.inflate<ItemTodolistBinding>(LayoutInflater.from(parent.context),R.layout.item_todolist, parent, false)

        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ToDoListAdapter.ViewHolder, position: Int) {
        val list: List<ToDoList>? = toDoLists.value

        list?.apply {
            holder.primaryKey.text = this.get(position).todolistPrimaryKey.toString()
            holder.title.text = this.get(position).title
            holder.content.text = this.get(position).content
            holder.isFinish.isChecked = this.get(position).isFinish
        }
        holder.isFinish.setOnCheckedChangeListener { buttonView, isChecked ->
            if (isChecked) {
                val deletedNo = holder.primaryKey.text.toString().toInt()

                // 체크박스가 체크 되면 매개변수로 받은 doneTodoList가 콜백됨.
                if (doneTodoList != null) {
                    doneTodoList.invoke(deletedNo)
                }
            }
        }
    }

    override fun getItemCount(): Int {
        Log.d(TAG,"ToDoListAdapter - getItemCount() called")
        return toDoLists.value?.size ?: 0
    }
}

액티비티에선 아래와 같이 매개변수를 넘겨줬다.

        val toDoListAdapter = ToDoListAdapter(viewModel.toDoLists
            ,fun(primaryKey: Int) {
            doneToDoList(primaryKey)    // viewModel에 doneToDoList를 호출.
        })

 

 

솔직히 이게 좋은 코드인지는 모르겠지만 내가 찾아본 답변 중에선 그나마 제일 나아 보인 방법 같다.

RxJava나 안드로이드에 대해 더 공부하면 수정 가능하지 않을까?

 

깃허브

 

GitHub - hwang434/todolist

Contribute to hwang434/todolist development by creating an account on GitHub.

github.com

 

728x90
반응형