Home > database >  Having 2 model class(dataClass) in adapter(ListAdapter)
Having 2 model class(dataClass) in adapter(ListAdapter)

Time:10-20

Recently, I faced with a issue that is a bit hard for me to solve

I need to put 2 models in List adapter, but it always says 2 type arguments expected

Image of the code and error

here is my whole adapter 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)

}

whenever i placed secound model here:

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

it says 2 type argument expected.

I don't know if it helps you or not but some one told me I have to use join in Kotlin

THANKS FOR YOUR ANSWERS :)

CodePudding user response:

You can build the list based on only a single data source. If you want to have multiple data sources, you should create a third data model and add the other two models in it.

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

ListView/Recycler view will create number of list items based on the list of objects passed.

ListAdapter<ListData, RecyclerView.ViewHolder> 

CodePudding user response:

ListAdaper can only accept one data model however you can add multiple items using another class like 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
    }
}

and deal with this only class in your ListAdapter for your code you will need to apply this changes

class TransactionHistory() :
    ListAdapter<DataItem, RecyclerView.ViewHolder>(BillDiffCallback()) {
    private val ITEM_VIEW_TYPE_EMPTY = 0
    private val ITEM_VIEW_TYPE_ITEM = 1

    private val adapterScope = CoroutineScope(Dispatchers.Default)

    fun addTransactions(list: List<Transaction>?) {
        adapterScope.launch {
            val items: List<DataItem> = when {
                list == null || list.isEmpty()  -> listOf(DataItem.Empty)
                else -> list.map { DataItem.TransactionItem(it) }
            }
            withContext(Dispatchers.Main) {
                submitList(items)
            }
        }
    }

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

    override fun getItemViewType(position: Int): Int {
        return when (getItem(position)) {
            is DataItem.Empty -> ITEM_VIEW_TYPE_EMPTY
            is DataItem.TransactionItem -> ITEM_VIEW_TYPE_ITEM
        }
    }
}

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

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