使用分页适配器(分页 3)的嵌套 recyclerview 在滚动后显示错误图像
nested recyclerview using paging adapter (paging 3) show wrong image after scrolling
如何解决滚动后子适配器图像变化和显示错误的图像?
这是我的代码
父数据Class
data class Review(
val author: String,
val date: String,
val rating: Float,
val comment: String,
val images: List<Image>)
子数据Class
作者和评论,我只取父数据class
data class Image(
var author: String? = null,
var comment: String? = null,
val large: String,
val thumbnail: String)
父适配器
class ReviewAdapter(private val callback: ProductReviewImageAdapterCallback) :
PagingDataAdapter<Review, ReviewAdapter.ListViewHolder>(DIFF_CALLBACK) {
private val viewPool = RecyclerView.RecycledViewPool()
private val imageAdapter: ProductReviewImageAdapter by lazy {
ProductReviewImageAdapter(callback)
}
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Review>() {
override fun areItemsTheSame(oldItem: Review, newItem: Review): Boolean {
return oldItem.author == newItem.author
}
override fun areContentsTheSame(oldItem: Review, newItem: Review): Boolean {
return oldItem.comment == newItem.comment
}
}
}
inner class ListViewHolder(itemBinding: ItemProductReviewBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
val binding = ItemProductReviewBinding.bind(itemBinding.root)
fun bind(data: Review, position: Int) {
with(binding) {
if (data.images.isEmpty()) {
rvImageReview.gone()
} else {
setupImagesRecyclerView(rvImageReview)
rvImageReview.visible()
imageAdapter.differ.submitList(data.images)
}
tvNameReviewer.text = data.author
tvReviewDesc.text = data.comment
tvDateReview.text = data.date
ratingBarReview.rating = data.rating
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder =
ListViewHolder(
ItemProductReviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val review = getItem(position)
if (review != null) {
holder.bind(review, position)
}
}
private fun setupImagesRecyclerView(recyclerView: RecyclerView) {
recyclerView.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
adapter = imageAdapter
setRecycledViewPool(viewPool)
setItemViewCacheSize(20)
}
}
}
子适配器
class ProductReviewImageAdapter(private val callback: ProductReviewImageAdapterCallback) : RecyclerView.Adapter<ProductReviewImageAdapter.ListViewHolder>() {
private val diffCallback = object : DiffUtil.ItemCallback<Image>() {
override fun areItemsTheSame(
oldItem: Image,
newItem: Image
): Boolean {
return oldItem.author == newItem.author
}
override fun areContentsTheSame(
oldItem: Image,
newItem: Image
): Boolean {
return oldItem.comment == newItem.comment
}
}
val differ = AsyncListDiffer(this, diffCallback)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder =
ListViewHolder(
ItemImageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun getItemCount(): Int = differ.currentList.size
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
holder.bind(differ.currentList[position], position)
}
inner class ListViewHolder(itemBinding: ItemImageBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private val itemBinding = ItemImageBinding.bind(itemBinding.root)
fun bind(data: Image, position: Int) {
with(itemBinding) {
image.loadImageRoundedCorner(data.thumbnail)
image.setOnClickListener {
callback.onProductReviewImageClicked(position, differ.currentList)
}
}
}
}
}
滚动前
第一次加载时,第一个位置数据显示相应的图像
before scrolling
稍微滚动一下后
第一个位置数据中的图像变为下一个数据中的图像
after a bit scrolling
滚动到最后 data/page
最后一张图片显示不合适的图片
scroll to last data/page
*注
- 只有5个数据,只有第一个和最后一个数据包含图像
- 第一个位置数据中的图像应该是人物图像,最后一个位置图像应该是粉红色图像
- 我使用 Coil 作为图像加载器,并且在加载图像之前使用了 ImageView.clear() 方法
提前致谢,抱歉,如果我的英语不好。我不是母语人士
更新
已修复:
原来只是adapter初始化的时候出错,adapter应该在onBindViewHolder中初始化,而不是在parent adapter中初始化,这样不是所有的item都有相同的adapter导致所有数据都改变
如何解决滚动后子适配器图像变化和显示错误的图像?
这是我的代码
父数据Class
data class Review(
val author: String,
val date: String,
val rating: Float,
val comment: String,
val images: List<Image>)
子数据Class
作者和评论,我只取父数据class
data class Image(
var author: String? = null,
var comment: String? = null,
val large: String,
val thumbnail: String)
父适配器
class ReviewAdapter(private val callback: ProductReviewImageAdapterCallback) :
PagingDataAdapter<Review, ReviewAdapter.ListViewHolder>(DIFF_CALLBACK) {
private val viewPool = RecyclerView.RecycledViewPool()
private val imageAdapter: ProductReviewImageAdapter by lazy {
ProductReviewImageAdapter(callback)
}
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Review>() {
override fun areItemsTheSame(oldItem: Review, newItem: Review): Boolean {
return oldItem.author == newItem.author
}
override fun areContentsTheSame(oldItem: Review, newItem: Review): Boolean {
return oldItem.comment == newItem.comment
}
}
}
inner class ListViewHolder(itemBinding: ItemProductReviewBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
val binding = ItemProductReviewBinding.bind(itemBinding.root)
fun bind(data: Review, position: Int) {
with(binding) {
if (data.images.isEmpty()) {
rvImageReview.gone()
} else {
setupImagesRecyclerView(rvImageReview)
rvImageReview.visible()
imageAdapter.differ.submitList(data.images)
}
tvNameReviewer.text = data.author
tvReviewDesc.text = data.comment
tvDateReview.text = data.date
ratingBarReview.rating = data.rating
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder =
ListViewHolder(
ItemProductReviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val review = getItem(position)
if (review != null) {
holder.bind(review, position)
}
}
private fun setupImagesRecyclerView(recyclerView: RecyclerView) {
recyclerView.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
adapter = imageAdapter
setRecycledViewPool(viewPool)
setItemViewCacheSize(20)
}
}
}
子适配器
class ProductReviewImageAdapter(private val callback: ProductReviewImageAdapterCallback) : RecyclerView.Adapter<ProductReviewImageAdapter.ListViewHolder>() {
private val diffCallback = object : DiffUtil.ItemCallback<Image>() {
override fun areItemsTheSame(
oldItem: Image,
newItem: Image
): Boolean {
return oldItem.author == newItem.author
}
override fun areContentsTheSame(
oldItem: Image,
newItem: Image
): Boolean {
return oldItem.comment == newItem.comment
}
}
val differ = AsyncListDiffer(this, diffCallback)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder =
ListViewHolder(
ItemImageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun getItemCount(): Int = differ.currentList.size
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
holder.bind(differ.currentList[position], position)
}
inner class ListViewHolder(itemBinding: ItemImageBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private val itemBinding = ItemImageBinding.bind(itemBinding.root)
fun bind(data: Image, position: Int) {
with(itemBinding) {
image.loadImageRoundedCorner(data.thumbnail)
image.setOnClickListener {
callback.onProductReviewImageClicked(position, differ.currentList)
}
}
}
}
}
滚动前
第一次加载时,第一个位置数据显示相应的图像
before scrolling
稍微滚动一下后
第一个位置数据中的图像变为下一个数据中的图像
after a bit scrolling
滚动到最后 data/page
最后一张图片显示不合适的图片
scroll to last data/page
*注
- 只有5个数据,只有第一个和最后一个数据包含图像
- 第一个位置数据中的图像应该是人物图像,最后一个位置图像应该是粉红色图像
- 我使用 Coil 作为图像加载器,并且在加载图像之前使用了 ImageView.clear() 方法
提前致谢,抱歉,如果我的英语不好。我不是母语人士
更新
已修复: 原来只是adapter初始化的时候出错,adapter应该在onBindViewHolder中初始化,而不是在parent adapter中初始化,这样不是所有的item都有相同的adapter导致所有数据都改变