【问题标题】:Having 2 model class(dataClass) in adapter(ListAdapter)在适配器(ListAdapter)中有 2 个模型类(dataClass)
【发布时间】:2021-10-19 12:28:21
【问题描述】:

最近,我遇到了一个对我来说有点难以解决的问题

我需要在 List 适配器中放置 2 个模型,但它总是说需要 2 种类型的参数

Here is the Link of the whole project

我想在 ListAdapter 中有 Transaction 和 Bank 模型

您可以阅读项目自述文件。 我想要 2 个模型的适配器在 ui.TransactionHistory 中

这是我的整个适配器类:

    class TransactionHistory() :
        ListAdapter<Transaction, 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)
//                holder.bind2(Bank, clickListener)
            }
            is EmptyViewHolder -> {
                holder.bind()
            }
        }
    }

    lateinit var clickListener: AdapterListener2
    fun setOnclickListener(listener: AdapterListener2) {
        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: ItemUserTransactionListBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Transaction, adapterListener2: AdapterListener2) {
            binding.transaction = item
            binding.clickListener = adapterListener2
            binding.executePendingBindings()
            if (item.type == "payPayment") {
                binding.transactionStatus.text = "برداخت قسط"
            } else if (item.type == "decrease") {
                binding.transactionStatus.text = "برداشت"
            } else if (item.type == "increase") {
                binding.transactionStatus.text = "واریز"
            }

            if (item.decrease == null) {
                binding.amount.text = item.increase
            } else {
                binding.amount.text = item.decrease
            }
        }

        fun bind2(item2: Bank, adapterListener2: AdapterListener2) {
            binding.bankInfo = item2
            binding.clickListener = adapterListener2
            binding.executePendingBindings()
        }

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

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

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


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

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

class AdapterListener2(
    val clickListener: (id: Long?) -> Unit,
    val deleteListener: (category: Transaction) -> Unit

) {
    fun onclick(transaction: Transaction) = clickListener(transaction.userId)
    fun onDeleteClick(userInfo: Transaction) = deleteListener(userInfo)

}

每当我在这里放置第二个模型时:

 ListAdapter<Transaction, **Bank**, RecyclerView.ViewHolder>(BillDiffCallback()) {}

它说需要 2 种类型的参数。

我不知道它是否对你有帮助,但有人告诉我我必须在 Kotlin 中使用 join

感谢您的回答:)

【问题讨论】:

    标签: android database kotlin join android-recyclerview


    【解决方案1】:

    ListAdaper 只能接受一个数据模型,但是您可以使用另一个类添加多个项目,例如 Sealed Class

    sealed class DataItem {
        abstract val id: Long
    
        data class TransactionItem(val transaction: Transaction): DataItem() {
            override val id = transaction.transId
        }
    
        object Empty: DataItem() {
            override val id = Long.MIN_VALUE
        }
    }
    

    并在 ListAdapter 中为您的代码处理这个唯一的类,您需要应用此更改

        class TransactionHistory() :
        ListAdapter<DataItem, RecyclerView.ViewHolder>(BillDiffCallback()) {
        private val ITEM_VIEW_TYPE_EMPTY = 0
        private val ITEM_VIEW_TYPE_ITEM_TRANSACTION = 1
        private val ITEM_VIEW_TYPE_ITEM_BANK = 2
    
        private val adapterScope = CoroutineScope(Dispatchers.Default)
    
        /**
         * DO NOT USE .submit(), use the method bellow
         */
    
        fun addTransactionsAndBanks(transactionList: List<Transaction>?, bankList: List<Bank>?) {
            adapterScope.launch {
                val transactionItems: List<DataItem> = when {
                    transactionList == null || transactionList.isEmpty() -> listOf(DataItem.Empty)
                    else -> transactionList.map { DataItem.TransactionItem(it) }
                }
                val bankItems: List<DataItem> = when {
                    bankList == null || bankList.isEmpty() -> listOf(DataItem.Empty)
                    else -> bankList.map { DataItem.BankItem(it) }
                }
    
                val items = transactionItems + bankItems
                withContext(Dispatchers.Main) {
                    submitList(items)
                }
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return when (viewType) {
                ITEM_VIEW_TYPE_ITEM_TRANSACTION -> ViewHolder.from(parent)
                ITEM_VIEW_TYPE_ITEM_BANK -> 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 -> {
                    when (val item = getItem(position)) {
                        is DataItem.TransactionItem -> holder.bind(item.transaction, clickListener)
                        is DataItem.BankItem -> holder.bind2(item.bank, clickListener)
                    }
                }
                is EmptyViewHolder -> holder.bind()
            }
        }
    
        lateinit var clickListener: AdapterListener2
        fun setOnclickListener(listener: AdapterListener2) {
            clickListener = listener
        }
    
    
        override fun getItemViewType(position: Int): Int {
            return when (getItem(position)) {
                is DataItem.Empty -> ITEM_VIEW_TYPE_EMPTY
                is DataItem.TransactionItem -> ITEM_VIEW_TYPE_ITEM_TRANSACTION
                is DataItem.BankItem -> ITEM_VIEW_TYPE_ITEM_BANK
            }
        }
    
        class ViewHolder
        private constructor(val binding: ItemUserTransactionListBinding) :
            RecyclerView.ViewHolder(binding.root) {
            fun bind(item: Transaction, adapterListener2: AdapterListener2) {
                binding.transaction = item
                binding.clickListener = adapterListener2
                binding.executePendingBindings()
                if (item.type == "payPayment") {
                    binding.transactionStatus.text = "برداخت قسط"
                } else if (item.type == "decrease") {
                    binding.transactionStatus.text = "برداشت"
                } else if (item.type == "increase") {
                    binding.transactionStatus.text = "واریز"
                }
    
                if (item.decrease == null) {
                    binding.amount.text = item.increase
                } else {
                    binding.amount.text = item.decrease
                }
            }
    
            fun bind2(item2: Bank, adapterListener2: AdapterListener2) {
                binding.bankInfo = item2
                binding.clickListener = adapterListener2
                binding.executePendingBindings()
            }
    
            companion object {
                fun from(parent: ViewGroup): ViewHolder {
                    val layoutInflater = LayoutInflater.from(parent.context)
                    val binding = ItemUserTransactionListBinding.inflate(layoutInflater, parent, false)
                    return ViewHolder(binding)
                }
            }
        }
    }
    
    class EmptyViewHolder private constructor(val binding: ItemUserTransactionListBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind() {
            binding.executePendingBindings()
        }
    
        companion object {
            fun from(parent: ViewGroup): EmptyViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val binding = ItemUserTransactionListBinding.inflate(layoutInflater, parent, false)
                return EmptyViewHolder(binding)
            }
        }
    }
    
    
    class BillDiffCallback : DiffUtil.ItemCallback<DataItem>() {
        override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
            return oldItem.id == newItem.id
        }
    
        override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
            return oldItem == newItem
        }
    }
    
    class AdapterListener2(
        val clickListener: (id: Long?) -> Unit,
        val deleteListener: (category: Transaction) -> Unit
    
    ) {
        fun onclick(transaction: Transaction) = clickListener(transaction.userId)
        fun onDeleteClick(userInfo: Transaction) = deleteListener(userInfo)
    
    }
    
    sealed class DataItem {
        abstract val id: Long
    
        data class TransactionItem(val transaction: Transaction) : DataItem() {
            override val id = transaction.transId
        }
    
        data class BankItem(val bank: Bank) : DataItem() {
            override val id = bank.bankId
        }
    
        object Empty : DataItem() {
            override val id = Long.MIN_VALUE
        }
    }
    

    【讨论】:

    • 所以我应该把我的第二个数据类放在哪里,我认为你的代码都是关于事务类的
    • 你需要创建一个DataItem密封类并在ListAdapter中使用它同时将diffUtil项回调更改为使用dataItem类,
    • 如果列表为空或为空,调用addTransactions方法时会添加第二个数据类“空类”
    • 请查看问题更新
    • 我更新了我的答案,你能再检查一下吗?
    【解决方案2】:

    您可以仅基于单个数据源构建列表。如果您想拥有多个数据源,您应该创建第三个数据模型并将其他两个模型添加到其中。

    data class ListData(val transaction : Transaction , val Bank : Bank)
    

    ListView/Recycler 视图将根据传递的对象列表创建列表项的数量。

    ListAdapter<ListData, RecyclerView.ViewHolder> 
    

    【讨论】:

    • 感谢您的评论,但我不想创建新课程。我正在努力在适配器中做一些事情。你的回答是一个可以接受的解决方案,我会试试谢谢。
    • 如果有,能否请您发布第三个数据模型类代码?你知道,我不知道如何调用第三个数据类中的模型类。
    • @AmirAndroidDeveloper 检查更新的答案。
    • 检查问题更新
    【解决方案3】:

    我找到了我的问题的答案

    我们必须在查询中使用 Join:

    //for single info
     @Query("SELECT `transaction`.increase, `transaction`.decrease, bank.bank_name From `transaction` JOIN bank WHERE `transaction`.bank_id=:key ")
        fun joinTables(key: Long): LiveData<TransactionAndBank>?
    
    
    
    //for list of info
     @Query("SELECT `transaction`.increase, `transaction`.decrease,`transaction`.type, bank.bank_name From `transaction` JOIN bank WHERE `transaction`.bank_id=:key ")
        fun joinAllTables(key: Long): LiveData<List<TransactionAndBank>>
    

    我必须把它放在 TransactionDAO 中

    source

    【讨论】:

      猜你喜欢
      • 2021-06-03
      • 1970-01-01
      • 2011-07-24
      • 1970-01-01
      • 2019-10-28
      • 1970-01-01
      • 2016-10-26
      • 2021-05-06
      • 1970-01-01
      相关资源
      最近更新 更多