Reputation: 150
I'm attempting to write a basic Todo list in Kotlin but wanted to use the recommended best practices and Android architecture components. At this point I have the basic architecture set up and there is a RecyclerView list of items stored in the database with a checkbox on the left side, and a description to the right. So far the list automatically updates when new data is added (via the floating action button). Now I want to update the record immediately whenever the checkbox is clicked for a particular item.
I can't figure out how or where to set the checkbox listener in order to pass the checked state and the item id to the ViewModel in order to update the data in the database. I thought about defining the listener directly inside the adapter, but then I can't find any way to call my ViewModel's update method. But then if I set up the listener in the fragment and pass that to the adapter, I can't find a way to get the id of the item.
This is my current fragment:
class ChecklistFragment : Fragment() {
private lateinit var checklistViewModel: ChecklistViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_checklist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Set up RecyclerView
items_list.layoutManager = LinearLayoutManager(activity)
val adapter = ToDoItemAdapter(object: CompoundButton.OnCheckedChangeListener {
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
Toast.makeText(activity, "checked", Toast.LENGTH_SHORT).show()
}
})
items_list.adapter = adapter
// Set up ViewModel
checklistViewModel = ViewModelProviders.of(this).get(ChecklistViewModel::class.java)
checklistViewModel.allToDoItems.observe(this, Observer { toDoItems ->
toDoItems?.let { adapter.setToDoItems(it) }
})
// Set up fab
add_list_item_fab.setOnClickListener {
checklistViewModel.insert(ToDoItem(description = "Item ${Random.nextInt(1,999)}", checked = Random.nextBoolean()))
}
}
}
This is my current adapter:
class ToDoItemAdapter(val onCheckedChangeListener: CompoundButton.OnCheckedChangeListener) : RecyclerView.Adapter<ToDoItemAdapter.ViewHolder>() {
private var toDoItems = emptyList<ToDoItem>()
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val checkbox: CheckBox = view.checkbox
val tvDescription: TextView = view.tv_description
fun bind(position: Int) {
checkbox.isChecked = toDoItems[position].checked
checkbox.setOnCheckedChangeListener(onCheckedChangeListener)
tvDescription.text = toDoItems[position].description
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.checklist_item, parent, false)
return ViewHolder(itemView)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(position)
}
override fun getItemCount() = toDoItems.size
internal fun setToDoItems(toDoItems: List<ToDoItem>) {
this.toDoItems = toDoItems
notifyDataSetChanged()
}
}
What is a best practice approach to listening to checked items and immediately storing those changes in the database using the MVVM architecture?
Upvotes: 1
Views: 1656
Reputation: 4611
If you want to click or check something in RecyclerView Item,
There is a elegant way for that.
class MyAdapter(val viewModel : ViewModel) : RecyclerView.ViewModel<ViewHolder>{
fun onCreateViewModel(..){
val binding = ItemRecyclerViewBinding.inflate(LayoutInflater.from(parent.context), parent,false)
binding.vm = viewModel
}
}
in XML
<data>
<variable name="vm" type="YourViewModel"/
<variable name="yourItem" type="YourItem"/
</data>
<FrameLayout or something
android:onClick = "@{(view) -> vm.onClickItem(view, yourItem)}">
</FrameLayout>
in ViewModel Class,
fun onClickItem(view : View, yourItem : YourItem){
Log.e(TAG,"$view is clicked with $yourItem")
}
I write about how to listen click or check event from recyclerview items
If you want how to store these datas to DB, you can use your own routine for that in ViewModel Class
Happy coding!
Upvotes: 1