提问人:Jojo Drink 提问时间:11/16/2023 更新时间:11/17/2023 访问量:49
在 Android 上使用 DiffUtils 到 Recyclerview 适配器中
Use DiffUtils into Recyclerview adapter on Android
问:
在我的应用程序中,我想将带有 DiffUtils 的 recyclerview 用于 recyclerview 适配器。
当我在项目之间滚动时,项目会变得混乱和移动。
我应该将此代码添加到onBindViewHolder中以解决此问题!
但是我不想禁用回收器视图模式!
我的代码:holder.setIsRecyclable(false)
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]
}
}
如何解决此问题?
答:
1赞
Anna Andreeva Rogotulka
11/17/2023
#1
您应该从适配器中删除字段 “binding”,它应该是 的属性,因为每个引用都有自己的 。相反,将其作为构造函数参数传递给 ViewHolder,也不需要创建“内部”,因为它是一个独立的实体。ViewHolder
ViewHolder
View
ViewHolder
编辑:
class ReservedListAdapter @Inject constructor() : RecyclerView.Adapter<ReservedListAdapter.ViewHolder>() {
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 {
val binding = ItemReservedListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(moviesList[position])
}
override fun getItemCount() = moviesList.size
//override fun getItemId(position: Int) = position.toLong()
private class ViewHolder(private val binding: ItemReservedListBinding) : RecyclerView.ViewHolder(binding) {
@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)
}
}
评论
0赞
Jojo Drink
11/17/2023
谢谢你的帮助,你能把代码发给我吗?请。我真的需要你的帮助。谢谢
0赞
Anna Andreeva Rogotulka
11/17/2023
@JojoDrink我用代码更新我的答案,希望它有所帮助
评论