kotlinmvvmandroid-recyclerviewandroid-roomdelete-row

How to delete a record in room database with recyclerview MVVM


I need to delete an item recyclerview adapter which should be notified in room database, please help me in finding a solution and thanks in advance

 class ListAdapter : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {
private lateinit var mitemsViewModel: ItemsViewModel
private var itemsList = emptyList<Item>()
private lateinit var item: Item
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    return MyViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.item_row_layout, parent, false)
    )
}
override fun getItemCount(): Int {
    return itemsList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    item = itemsList.get(position)
    //always remember this technique to save the values in val type
    val currentItem = itemsList[position]
    holder.itemView.itemNameTV.text = currentItem.itemName.toString()
    holder.itemView.itemCodeTV.text = currentItem.itemCode.toString()
    holder.itemView.itemCategoryTV.text = currentItem.itemCategory.toString()
    holder.itemView.itemDescriptionTV.text = currentItem.itemDescription.toString()
    holder.itemView.itemSellingPriceTV.text = currentItem.itemSellingPrice.toString()
    holder.itemView.itemStockTV.text = currentItem.itemStock.toString()
    holder.itemView.deleteItem.setOnClickListener {
        val itName = holder.itemView.itemNameTV.text.toString()
        val itCode = holder.itemView.itemCodeTV.text.toString()
        val itCategory = holder.itemView.itemCategoryTV.text.toString()
        val itDescription = holder.itemView.itemDescriptionTV.text.toString()
        val itSellingPrice = holder.itemView.itemSellingPriceTV.text.toString()
        val itStock = holder.itemView.itemStockTV.text.toString()
        val itime = Item(0, itName, itCode, itCategory, itSellingPrice, itStock, itDescription)
        mitemsViewModel.deleteItem(itime)
        //dao.deleteItem(itemsList.get(position))
    }
}
fun setData(item: List<Item>) {
    this.itemsList = item
    notifyDataSetChanged()

}}

Help me how to initialize the ViewModel in recyclerview adapter. The error code after running my app

 kotlin.UninitializedPropertyAccessException: lateinit property mitemsViewModel has not been initialized
    at com.manju.mobilebilling.ui.items.ListAdapter.onBindViewHolder$lambda-0(ListAdapter.kt:65)
    at com.manju.mobilebilling.ui.items.ListAdapter.$r8$lambda$pJauI4KaymNCF6j043M3H3t3CwQ(ListAdapter.kt)
    at com.manju.mobilebilling.ui.items.ListAdapter$$ExternalSyntheticLambda0.onClick(D8$$SyntheticClass)
    at android.view.View.performClick(View.java:5651)
    at android.view.View$PerformClick.run(View.java:22445)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6138)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)

Solution

  • You should initialize the ItemsViewModel in the parent Activity or Fragment:

    private val viewModel by viewModels<ItemsViewModel>()
    

    Then, instead of passing it directly to the ListAdapter declare a custom click listener and use that as parameter:

    // Add a parameter in the adapter
    class ListAdapter(
        private val clickListener: ListClickListener
    ) : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {
    
        private var itemsList = emptyList<Item>()
        private lateinit var item: Item
    
        class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
            return MyViewHolder(
                LayoutInflater.from(parent.context).inflate(R.layout.item_row_layout, parent, false)
            )
        }
    
        override fun getItemCount(): Int {
            return itemsList.size
        }
    
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            item = itemsList.get(position)
            //always remember this technique to save the values in val type
            val currentItem = itemsList[position]
            holder.itemView.itemNameTV.text = currentItem.itemName.toString()
            holder.itemView.itemCodeTV.text = currentItem.itemCode.toString()
            holder.itemView.itemCategoryTV.text = currentItem.itemCategory.toString()
            holder.itemView.itemDescriptionTV.text = currentItem.itemDescription.toString()
            holder.itemView.itemSellingPriceTV.text = currentItem.itemSellingPrice.toString()
            holder.itemView.itemStockTV.text = currentItem.itemStock.toString()
            holder.itemView.deleteItem.setOnClickListener {
                val itName = holder.itemView.itemNameTV.text.toString()
                val itCode = holder.itemView.itemCodeTV.text.toString()
                val itCategory = holder.itemView.itemCategoryTV.text.toString()
                val itDescription = holder.itemView.itemDescriptionTV.text.toString()
                val itSellingPrice = holder.itemView.itemSellingPriceTV.text.toString()
                val itStock = holder.itemView.itemStockTV.text.toString()
                val itime = Item(0, itName, itCode, itCategory, itSellingPrice, itStock, itDescription)
                // Call the click listener
                clickListener.onClick(iitem)
            }
        }
    
        fun setData(item: List<Item>) {
            this.itemsList = item
            notifyDataSetChanged()
    
        }
    }
    
    // Click listener class
    class ListClickListener(val clickListener: (item: Item) -> Unit) {
        fun onClick(item: Item) = clickListener(item)
    }
    

    Finally, declare your ListAdapter in the parent Activity or Fragment with:

    val adapter = ListAdapter(ListClickListener { item -> 
        viewModel.deleteItem(item)
    })