【问题标题】:Connect viewmodel class to adapter(recyclerview)将视图模型类连接到适配器(recyclerview)
【发布时间】:2021-12-30 20:41:46
【问题描述】:

我有一个名为 UserListViewModel 的 viewModel 类,在那个类上有一个名为 sumUserIncrease 的函数,我想获取该函数的值并将其发送到适配器以在 recyclerview 中显示我希望你明白我的意思,如果没有,看看这个:

这是我的 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)
    }
}

我的适配器:

 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)
}

【问题讨论】:

    标签: android kotlin android-recyclerview adapter viewmodel


    【解决方案1】:

    让您的UserListViewModel 包含您的Fragment/Activity 观察到的LiveData。一旦它获得更新,它将发送到Adapter

    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
    }
    

    Fragment/Activity

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

    Adapter

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

    但这有点不寻常。你真正想要做的是通过一个新的UserInfo 更改总和。让DiffCallback 换一个不同的。您可能想要做的是实现 Paging https://proandroiddev.com/paging-3-easier-way-to-pagination-part-1-584cad1f4f61 这将允许您在应用程序的任何位置更改数据库中的内容。发生这种情况时,数据将在Adapter 中更新。它有点复杂,但一旦你开始工作,你就会后悔。

    【讨论】:

    • 谢谢@avalerio,但我还需要做一件事
    • 我想在回收站视图中显示每个用户增加的总和。当我使用 sumUserIncrease 它为所有项目返回相同的数量。我有一个用户列表,我在回收站视图和回收站视图中显示它们,当然我们有一个名为 itemUserList 的 xml 我想在该 xml 上显示例如 user1 的总和增加。我希望你明白我想说的话
    • 所以分页是我的解决方案?不是吗?
    • 看起来您使用的是Room。如果是这样,您将需要创建一个 data 类来表示用户事务和用户信息的组合。 developer.android.com/training/data-storage/room/… 让我们称之为UserInfoWithTransactions 然后您需要在RecyclerView 中显示它,而不仅仅是UserInfo。这样,当您绑定到ViewHolder 时,您将拥有两者。通过使用Paging3,对Transactions 表的更改将自动提取UserInfoWithTransactions 的新列表(包含新事务)。
    • 所以它类似于加入房间数据库?
    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 2023-03-08
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多