在 Android 上使用 DiffUtils 到 Recyclerview 适配器中

问题描述 投票:0回答:1

在我的应用程序中,我想将 recyclerviewDiffUtils 一起使用到 recyclerview 适配器中。
当我在项目之间滚动时,项目会变得混乱并移动。
我应该将这段代码

holder.setIsRecyclable(false)
添加到 onBindViewHolder 中来解决这个问题!
但我不想禁用 recyclerview 模式!
我的代码:

class ReservedListAdapter @Inject constructor() : RecyclerView.Adapter<ReservedListAdapter.ViewHolder>() {

    private lateinit var binding: ItemReservedListBinding
    private lateinit var context: Context
    private var moviesList = emptyList<Result>()
    private val userToken by lazy { GoodPrefs.getInstance().getString(USER_TOKEN, "") }
    private var selectedType = ""

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        binding = ItemReservedListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        context = parent.context
        return ViewHolder()
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(moviesList[position])
        holder.setIsRecyclable(false)
    }

    override fun getItemCount() = moviesList.size

    //override fun getItemId(position: Int) = position.toLong()

    inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {

        @SuppressLint("SetTextI18n", "NotifyDataSetChanged", "CheckResult")
        fun bind(item: Result) {
            binding.apply {
                //Title
                var type = ""
                item.counseling?.let { counseling ->
                    type = if (counseling.type == PHONE) {
                        context.getString(R.string.byPhone)
                    } else {
                        context.getString(R.string.textual)
                    }
                    titleTxt.text = "${context.getString(R.string.visit)} $type - " +
                            context.getString(R.string.doctor) +
                            "${counseling.physician?.firstName} ${counseling.physician?.lastName}"
                }
                //Date
                if (item.startAt != null) {
                    val date = item.startAt.split(" ")[0]
                    val hour = item.startAt.split(" ")[1]
                    val showDate = if (item.counseling?.type == PHONE) {
                        "${date.convertDateToFarsiWithMonthName()} | " + "${context.getString(R.string.hour)} ${hour.dropLast(3)}"
                    } else {
                        "${date.convertDateToFarsiWithMonthName()} | ${context.getString(R.string.duringDay)}"
                    }
                    dateTxt.text = showDate
                }
                //Avatar
                if (item.counseling?.physician?.profile?.files != null) {
                    if (item.counseling.physician.profile.files.isNotEmpty()) {
                        item.counseling.physician.profile.files.forEach { file ->
                            if (file?.description == AVATAR) {
                                avatarLoading.visibility = View.VISIBLE
                                ApiClient.getInstance().apisUseCase().getAvatarImage(userToken, file.id!!)
                                    .applyIoScheduler()
                                    .subscribe({
                                        avatarLoading.visibility = View.GONE
                                        if (it.isSuccessful) {
                                            if (it.code() == 200) {
                                                if (it.body() != null) {
                                                    val decodedBytes: ByteArray =
                                                        Base64.decode(it.body()!!.data!!.file, Base64.DEFAULT)
                                                    avatarImg.load(decodedBytes)
                                                }
                                            }
                                        }
                                    }, {
                                        avatarLoading.visibility = View.GONE
                                    })
                            } else {
                                avatarImg.load(R.drawable.avatar_doctor)
                            }
                        }
                    }
                }
                //Status
                infoTxt.text = item.status
                infoTxt.setCorner(10)
                //Click
                binding.root.setOnClickListener {
                    notifyDataSetChanged()
                    onItemClickListener?.let {
                        it(item, selectedType)
                    }
                }
            }
        }
    }

    private fun dynamicallyStatusColor(textColor: Int, bgColor: Int) {
        binding.infoTxt.apply {
            setTextColor(ContextCompat.getColor(context, textColor))
            setBgColor(ContextCompat.getColor(context, bgColor))
        }
    }

    private var onItemClickListener: ((Result, String) -> Unit)? = null

    fun setOnItemClickListener(listener: (Result, String) -> Unit) {
        onItemClickListener = listener
    }

    fun setData(data: List<Result>) {
        val moviesDiffUtil = BaseDiffUtils(moviesList, data)
        val diffUtils = DiffUtil.calculateDiff(moviesDiffUtil)
        moviesList = data
        diffUtils.dispatchUpdatesTo(this)
    }
}

BaseDiffUtils 代码:

class BaseDiffUtils<T>(private val oldItem: List<T>, private val newItem: List<T>) : DiffUtil.Callback() {
    override fun getOldListSize(): Int {
        return oldItem.size
    }

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

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldItem[oldItemPosition] === newItem[newItemPosition]
    }

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

如何解决这个问题?

android kotlin android-recyclerview
1个回答
0
投票

您应该从适配器中删除“绑定”字段,它应该是

ViewHolder
的属性,因为每个
ViewHolder
都引用自己的
View
。相反,将其作为构造函数参数传递给 ViewHolder,也无需将
ViewHolder
设置为“内部”,因为它是一个独立的实体。

© www.soinside.com 2019 - 2024. All rights reserved.