Nick Wilde
Nick Wilde

Reputation: 175

Access DB from adapter (Kotlin)

I have a list of categories and i want to show the amount of items in each category. Using Room with MVVM architecture basically i want to use simple query in my adapter, to return its value (amount of items)

DAO

@Query("SELECT COUNT(id) FROM items WHERE listId=:listID")
suspend fun countItems(listID: Long):Int

Repo

suspend fun countItems(id: Long): Int{
        return itemsDao.countItems(id)
    }

Adapter

class ListsAdapter internal constructor(
    context: Context
) : RecyclerView.Adapter<ListsAdapter.ListViewHolder>() {

    private val inflater: LayoutInflater = LayoutInflater.from(context)
    private var lists = mutableListOf<ListItem>()

    inner class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val listName: TextView = itemView.findViewById(R.id.single_list_name)
        val listIcon: ImageView = itemView.findViewById(R.id.single_list_icon)
        val wAmount: TextView = itemView.findViewById(R.id.single_list_amount)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListsAdapter.ListViewHolder {
        val itemView = inflater.inflate(R.layout.single_list, parent, false)
        return ListViewHolder(itemView)
    }

    override fun getItemCount() = lists.size

    override fun onBindViewHolder(holder: ListsAdapter.ListViewHolder, position: Int) {
        val current = lists[position]
        holder.listName.text = current.name
     // holder.wAmount.text =

        holder.itemView.setOnClickListener {
            val bundle = bundleOf("list_id" to current.id,"list_name" to current.name)
            holder.itemView.findNavController().navigate(R.id.action_listsFragment_to_nav_items_list, bundle)
        }
    }

    internal fun setLists(lists: List<ListItem>) {
        this.lists = lists.toMutableList()
        notifyDataSetChanged()
    }

    internal fun listToDelete(viewHolder: RecyclerView.ViewHolder) : ListItem{
        val position = viewHolder.adapterPosition
        return lists[position]
    }

    internal fun removeList(viewHolder: RecyclerView.ViewHolder){
        lists.removeAt(viewHolder.adapterPosition)
        notifyItemRemoved(viewHolder.adapterPosition)
    }
}

Should it be done over ViewModel, but in that case it has to be passed to adapter? Or maybe there is better (cleaner) way to do it? Any help is appreciated. Thanks

Upvotes: 2

Views: 1240

Answers (1)

Basil
Basil

Reputation: 855

Adapters shouldn't be responsible for loading data from storage. The clean way to do it is to access the repo in your ViewModel, then pass the data to your Adapter. This also gives you the benefit of being able to handle errors in a straightforward way, as it would be easy to update the layout containing Adapter easily, unlike the spaghetti you'll need to do this from the adapter, in the addition to being a wrong design of course.

Another step would be to introduce a more layered architecture,like Uncle Bob's clean architecture

Upvotes: 3

Related Questions