在适配器(ListAdapter)中有 2 个模型 class(dataClass)

Having 2 model class(dataClass) in adapter(ListAdapter)

最近遇到一个比较难解决的问题

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

Here is the Link of the whole project

我想在 ListAdapter 中使用交易和银行模型

你可以阅读项目README。 我想要2个型号的适配器在ui.TransactionHistory

这是我的整个适配器 class:

    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

感谢您的回答:)

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

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

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

ListAdapter<ListData, RecyclerView.ViewHolder> 

ListAdaper 只能接受一个数据模型,但是您可以使用另一个 class 添加多个项目,例如 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 您的代码需要应用此更改

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

我找到了问题的答案

我们必须在查询中使用 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