首页 > 解决方案 > android在使用DiffUtil时更改RecyclerView中奇数行的背景颜色

问题描述

我有一个 RecyclerView 并且每个奇数行都有不同的背景颜色。我尝试添加DiffUtil以加快更新速度,如下所示:


import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.asdf.android.R
import com.asdf.android.network.model.trade.MarketTradeItem
import kotlinx.android.synthetic.main.row_trade_history.view.*

class MarketTradesListAdapter(
    private val context: Context,
    private var list: MutableList<MarketTradeItem>,
    val theme: Int
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflate =
            LayoutInflater.from(parent.context).inflate(R.layout.row_trade_history, parent, false)
        return ItemHolder(inflate)
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val itemHolder = holder as ItemHolder
        itemHolder.bind(list[position], position)
    }

    override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        if (payloads.isEmpty()) {
            super.onBindViewHolder(holder, position, payloads)
        } else {
            val payload = payloads[0] as DiffUtilPayload
            val itemHolder = holder as ItemHolder
            itemHolder.bind(list[position], position, payload)
        }
    }

    fun setList(it: List<MarketTradeItem>) {
        it.forEachIndexed { index, item -> item.position = index }

        DiffUtil.calculateDiff(DiffCallback(list, it),true).dispatchUpdatesTo(this)

        list.clear()
        list.addAll(it)
    }

    inner class ItemHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(
            order: MarketTradeItem,
            position: Int,
            payload: DiffUtilPayload = DiffUtilPayload()
        ) {


            var color: Int
            if (theme == R.style.Apptheme) {
                color = R.color.listBackgroundColorLight
            } else {
                color = R.color.listBackgroundColorDark
            }
//            if (payload.isPositionChanged)
            itemView.setBackgroundColor(
                if (position % 2 == 0) ContextCompat.getColor(
                    itemView.context,
                    android.R.color.transparent
                ) else
                    ContextCompat.getColor(itemView.context, color)
            )


            itemView.textViewPrice.setTextColor(
                ContextCompat.getColor(
                    itemView.context,
                    if (order.isRaise) R.color.buy_green else R.color.sell_red
                )
            )
            if (payload.isPriceChanged) {
                itemView.textViewPrice.text = order.price
            }
            if (payload.isAmountChanged) {
                itemView.textViewAmount.text = order.amount
            }
            if (payload.isTimeChanged) {
                itemView.textViewTime.text = order.time
            }


        }
    }

    class DiffCallback(
        private val oldList: List<MarketTradeItem>,
        private val newList: List<MarketTradeItem>
    ) : DiffUtil.Callback() {
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return oldList[oldItemPosition] == newList[newItemPosition]
        }

        override fun getOldListSize(): Int {
            return oldList.size
        }

        override fun getNewListSize(): Int {
            return newList.size
        }

        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return oldList[oldItemPosition] == newList[newItemPosition]
        }

        override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
            val oldItem = oldList[oldItemPosition]
            val newItem = newList[oldItemPosition]
            return DiffUtilPayload(
                oldItem.price != newItem.price,
                oldItem.amount != newItem.amount,
                oldItem.createdAt != newItem.createdAt,
                oldItem.time != newItem.time,
                oldItem.position != newItem.position
            )
        }

    }

    data class DiffUtilPayload(
        val isPriceChanged: Boolean = true,
        val isAmountChanged: Boolean = true,
        val isCreatedAtChanged: Boolean = true,
        val isTimeChanged: Boolean = true,
        val isPositionChanged: Boolean = true
    )

}

问题是,当新项目插入列表时,偶数行和奇数行的背景颜色显示不正确,如下所示:

在此处输入图像描述 背景颜色是随机设置的,不会显示为交替的偶数/奇数。我能做些什么来解决这个问题?

标签: androidandroid-recyclerviewandroid-diffutils

解决方案


我认为您需要更改areContentsTheSameDiffUtil 中的方法。如果内容相同,则不会计算不会notifyItemChanged(position)分发给适配器的更改。它不会要求onBindViewHolder那个职位/项目。

您应该尝试将方法更改为

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
    return oldList[oldItemPosition] == newList[newItemPosition] && oldItemPosition % 2 == newItemPosition % 2
}

推荐阅读