所以我找到了問題的根源。在我的 Recyclerview 配接器內部,我試圖檢查 imageName 是否為空或為空,如果不是,那么我們可以從本地存盤中獲取影像并將其放入持有者的 ImageView 中。當進行此檢查并且僅在配接器中的專案串列中的第一項中具有影像時,影像將被放置在多個位置......如果我繼續旋轉 recyclerview,它會不斷添加更多。我想這樣做的原因是因為我想要一個加號圖示的默認影像來觸發更多邏輯,否則如果它可用則存盤的影像。下面是產生問題的代碼的第一部分,以及一些圖片供您查看正在發生的事情。
package com.example.dukebox.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.dukebox.FORWARD_SLASH
import com.example.dukebox.R
import com.example.dukebox.RECORD_IMAGES
import com.example.dukebox.models.Record
import com.example.dukebox.viewmodel.HomeViewModel
class NumberSelectionAdapter(
private val recordInfoTitle: TextView,
private val viewModel: HomeViewModel
): RecyclerView.Adapter<NumberSelectionAdapter.ViewHolder>() {
var selectedPosition = 0
private var records: List<Record> = emptyList()
private val imagesPath = "${recordInfoTitle.context.getExternalFilesDir(null)?.absolutePath}$RECORD_IMAGES$FORWARD_SLASH"
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.number_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val record = records[position]
if (!record.imageName.isNullOrEmpty()){
Glide.with(recordInfoTitle.context).load("$imagesPath$FORWARD_SLASH${record.imageName}").into(holder.recordCover)
}
}
override fun getItemCount(): Int {
return records.size
}
fun updateList(newRecords: List<Record>) {
records = newRecords
notifyDataSetChanged()
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recordCover: ImageView = itemView.findViewById(R.id.recordCover)
}
}

然后是只將影像放在它應該在整個時間的位置的代碼。如您所見,唯一的區別是 onBindViewHolder 中的 null 或空檢查。
package com.example.dukebox.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.dukebox.FORWARD_SLASH
import com.example.dukebox.R
import com.example.dukebox.RECORD_IMAGES
import com.example.dukebox.models.Record
import com.example.dukebox.viewmodel.HomeViewModel
class NumberSelectionAdapter(
private val recordInfoTitle: TextView,
private val viewModel: HomeViewModel
): RecyclerView.Adapter<NumberSelectionAdapter.ViewHolder>() {
var selectedPosition = 0
private var records: List<Record> = emptyList()
private val imagesPath = "${recordInfoTitle.context.getExternalFilesDir(null)?.absolutePath}$RECORD_IMAGES$FORWARD_SLASH"
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.number_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val record = records[position]
Glide.with(recordInfoTitle.context).load("$imagesPath$FORWARD_SLASH${record.imageName}").into(holder.recordCover)
}
override fun getItemCount(): Int {
return records.size
}
fun updateList(newRecords: List<Record>) {
records = newRecords
notifyDataSetChanged()
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recordCover: ImageView = itemView.findViewById(R.id.recordCover)
}
}
還有一些它看起來像的圖片,因為它試圖加載一個不存在的影像,加號不存在。但影像只是它應該在的地方。我多次跨越它,而且只有一個。

uj5u.com熱心網友回復:
RecyclerViews重用(回收)他們ViewHolder的 s,所以onBindViewHolder你通常會得到一個已經為另一個專案顯示東西的東西。您需要對其進行更新,使其看起來適合您當前的專案。
這就是你在做什么
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val record = records[position]
// this ONLY updates IF there's an imageName
if (!record.imageName.isNullOrEmpty()){
Glide.with(recordInfoTitle.context).load("$imagesPath$FORWARD_SLASH${record.imageName}").into(holder.recordCover)
}
}
問題是如果有影像名稱,您就設定了一個新圖片 - 但如果沒有,您就不會清除它。因此,如果您獲得了一個ViewHolder先前顯示帶有影像的專案,那么該影像仍然存在!
如果您沒有明確洗掉它,它仍然會顯示舊資料。這適用于任何事情onBindViewHolder- 您需要將所有內容更新為當前專案的正確顯示狀態。這就是為什么當它應該只出現在第一個專案上時你會看到影像“重復”的原因——它只是ViewHolder用于第一個專案的影像再次出現,除非你更改 的內容,否則recordCover它每次都會出現
由于您使用的是 Glide,因此您應該使用它的clear()功能來擦除影像,如檔案中所述:
通過呼叫
clear()或into(View),View您將取消加載并保證 Glide 在呼叫完成后不會更改視圖的內容。如果您忘記呼叫clear()并且沒有開始新的加載,則在您設定特殊Drawable并將內容更改為View舊影像后,您開始加載到先前位置的同一視圖中可能會完成。
基本上,因為您告訴 Glide 將影像加載到特定ViewHolder的 'sImageView中,并且這可能異步發生,所以(如果您快速滾動)您可能會到達另一個使用它的專案ViewHolder,請將內容設定為空白,但隨后 Glide 將在延遲后顯示先前請求的影像并將其設定在ImageView.
通過使用clear()Glide 呼叫,它可以在內部跟蹤哪些作業在排隊,ImageView如果有新的作業進來,它可以取消該請求,包括清除它的請求。基本上,讓 Glide 來處理這一切!
所以:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val record = records[position]
// always update the ImageView to the correct state
if (!record.imageName.isNullOrEmpty()){
Glide.with(recordInfoTitle.context).load("$imagesPath$FORWARD_SLASH${record.imageName}").into(holder.recordCover)
} else {
Glide.with(recordInfoTitle.context).clear(holder.recordCover)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/497473.html
標籤:安卓 科特林 用户界面 android-recyclerview 旋转木马
