AmirHossein
AmirHossein

Reputation: 733

Connect viewmodel class to adapter(recyclerview)

I have viewModel class which name UserListViewModel And on that class there is function which named sumUserIncrease and I want to get that functions value and send that to adapter to show in recyclerview I hope you got what I mean if not, take look at this:

here is my userListViewModel:

class UserListViewModel(
val mUserInfoDAO: UserDAO,
val mTransactionDAO: TransactionsDAO,
val mLoanDAO: LoanDAO,
val mBankDAO: BankDAO,
application: Application
) :
    AndroidViewModel(application) {
    var viewModelJob = Job()
    val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
    fun sumAllIncrease(id: Long): Long {
        return mTransactionDAO.sumUserIncrease(id)
    }

    fun sumAllDecrease(id: Long): Long {
        return mTransactionDAO.sumUserDecrease(id)
    }
}

my Adapter:

 package com.example.holyquran.ui.userList
class UserAdapter() : ListAdapter<UserInfo, RecyclerView.ViewHolder>(BillDiffCallback()) {
    private val ITEM_VIEW_TYPE_EMPTY = 0

    private val ITEM_VIEW_TYPE_ITEM = 1
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {

        return when (viewType) {
            ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
            ITEM_VIEW_TYPE_EMPTY -> EmptyViewHolder.from(parent)
            else -> throw ClassCastException("Unknown viewType $viewType")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewHolder -> {
                val item = getItem(position)
                holder.bind(item, clickListener)
            }
            is EmptyViewHolder -> {
                holder.bind()
            }
        }
    }

    lateinit var clickListener: AdapterListener
    fun setOnclickListener(listener: AdapterListener) {
        clickListener = listener
    }


    override fun getItemViewType(position: Int): Int {
        return if (itemCount > 0)
            ITEM_VIEW_TYPE_ITEM
        else
            ITEM_VIEW_TYPE_EMPTY
    }

    class ViewHolder private constructor(val binding: ItemUserListBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: UserInfo, adapterListener: AdapterListener) {





            if (item.gender == "مرد") {
                binding.img.setImageResource(R.drawable.user_avata_male);
            }else{
                binding.img.setImageResource(R.drawable.user_avatar_female);
            }

            binding.userInfo = item
            binding.clickListener = adapterListener
            binding.executePendingBindings()
        }

        companion object {
            fun from(parent: ViewGroup): ViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val binding = ItemUserListBinding.inflate(layoutInflater, parent, false)
                return ViewHolder(binding)
            }
        }
    }

    class EmptyViewHolder private constructor(val binding: ItemUserListBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind() {
            binding.executePendingBindings()


        }

        companion object {
            fun from(parent: ViewGroup): EmptyViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val binding = ItemUserListBinding.inflate(layoutInflater, parent, false)
                return EmptyViewHolder(binding)
            }
        }
    }
}

class BillDiffCallback : DiffUtil.ItemCallback<UserInfo>() {
    override fun areItemsTheSame(oldItem: UserInfo, newItem: UserInfo): Boolean {
        return oldItem.userId == newItem.userId
    }

    override fun areContentsTheSame(
        oldItem: UserInfo,
        newItem: UserInfo
    ): Boolean {
        return oldItem == newItem
    }
}

class AdapterListener(
    val clickListener: (id: Long) -> Unit,
    val deleteListener: (userInfo: UserInfo) -> Unit,
    private val longClickListener: (id: Long) -> Unit

) {
    fun onclick(userInfo: UserInfo) = clickListener(userInfo.userId)
    fun onDeleteClick(userInfo: UserInfo) = deleteListener(userInfo)
    fun onLongClick(userInfo: UserInfo) = longClickListener(userInfo.userId)
}

Upvotes: 0

Views: 699

Answers (1)

avalerio
avalerio

Reputation: 2335

Have your UserListViewModel contain LiveData that your Fragment/Activity observes. Once it gets an update it will send it to the Adapter.

In ViewModel

private val currentSum : MutableLiveData<Int> = MutableLiveData(0)

fun sumAllIncrease(id: Long): Long {
    var sum = mTransactionDAO.sumUserIncrease(id)
    currentSum.value = sum
    return sum
}
fun sumAllDecrease(id: Long): Long {
    var sum = mTransactionDAO.sumUserDecrease(id)
    currentSum.value = sum
    return sum
}
fun getCurrentSum(): LiveData<Long> {
    return currentSum
}

In Fragment/Activity

viewModel.getCurrentSum().observe(this, Observer {
    adapter.setSum(it)
})

In Adapter

fun setSum(sum : Long){
    //The sum is now in you adapter.
    //Use it how you need too.
}

But this is kinda unusual. What you really want to do is pass a new UserInfo with the changed sum. And let the DiffCallback change the one that is different. What you probably want to do is implement Paging https://proandroiddev.com/paging-3-easier-way-to-pagination-part-1-584cad1f4f61 This will allow you to change stuff in the database anywhere in the app. When that happens the data will be updated in the Adapter. Its kinda complex but once you get it working you want regret it.

Upvotes: 1

Related Questions