如何从 RecyclerView Adapter 调用 ViewModel.delete?

How to call ViewModel.delete from RecyclerView Adapter?

我想从我的 Recyclerview 适配器调用我的 ViewModel.delete(房间数据库)方法,但它不起作用。有什么想法吗?

我想像这样调用 OnBindViewHolder 中的 ViewModel: holder.binding.ivItemWalletDelete.setOnClickListener{ 钱包视图模型... }

但我收到错误:空对象

RecyclerView 适配器(WalletListAdapter.kt)

class WalletListAdapter:
        ListAdapter<Wallet, WalletListAdapter.ViewHolder>(WalletDiffCallback()){

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        return ViewHolder.from(parent)
    }


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = getItem(position)
        holder.bind(item)
    }

    class ViewHolder private constructor(val binding: ItemWalletsBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(item: Wallet) {
            binding.wallet = item
            binding.executePendingBindings()
        }

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

class WalletDiffCallback : DiffUtil.ItemCallback<Wallet>() {
    override fun areItemsTheSame(oldItem: Wallet, newItem: Wallet): Boolean {
        return oldItem.walletId == newItem.walletId
    }

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

ViewModel (WalletViewModel.kt)

class WalletViewModel(application: Application): AndroidViewModel(application) {
    private val repository = WalletRepository(application)
    private val liveWalletList = repository.getLiveDataWallets()

    fun insert(wallet: Wallet){
        viewModelScope.launch {
            repository.insert(wallet)
        }
    }

    fun update(wallet: Wallet){
        viewModelScope.launch {
            repository.update(wallet)
        }
    }

    fun delete(wallet: Wallet){
        viewModelScope.launch {
            repository.delete(wallet)
        }
    }

    fun getWalletById(walletId: Long): Wallet? {
        var wallet: Wallet? = null
        viewModelScope.launch {
            wallet = repository.getWalletById(walletId)
        }
        return wallet
    }

    fun getAllWallets(): List<Wallet>? {
        var wallets: List<Wallet>? = null
        viewModelScope.launch {
            wallets = repository.getAllWallets()
        }
        return wallets
    }

    fun getLiveWalletList(): LiveData<List<Wallet>> = liveWalletList
} 

解决此类问题的一种常见方法是创建一个将传递给适配器的回调。

在您的 WalletListAdapter class 中传入一个接受 Wallet 对象的回调。

class WalletListAdapter(private val onDeleteCallback: (Wallet) -> Unit) {}

在您的 ViewHolder 中,您可以在每个回收器视图项目上设置一个 OnClickListener 并将 Wallet 对象传递给回调函数。那看起来像这样:

binding.root.setOnClickListener { onDeleteCallback(item) }

最后,初始化 WalletListAdapter 的视图(activity、片段等)将传入一个接受 Wallet 对象的函数。这是您随后调用 WalletViewModel 的删除函数的地方。

class WalletListActivity: Activity() {

  @Inject
  lateinit var viewModel: WalletViewModel

  override fun onCreate(bundle: Bundle?) {
    super.onCreate(savedInstanceState)
    
    // initialize the WalletListAdapter and pass in the callback
    val adapter = WalletListAdapter(::deleteWallet)

  }

  private fun deleteWallet(wallet: Wallet) {
    viewModel.delete(wallet)
  }

}

注意:可以先用空构造函数初始化WalletListAdapterclass,然后创建一个方法将回调函数从视图传递给WalletListAdapterclass.重点是将点击事件从适配器“传播”回视图,因此视图可以调用视图模型的方法。