我有下一個recyclerview實作Filterable類的配接器來嘗試在我productList的內部搜索并更新recyclerview。
class ProductsAdapterV2(
private val itemClickListener: OnProductClickListener
) : RecyclerView.Adapter<BaseViewHolder<*>>(), Filterable {
private var productsList = listOf<Product>()
private var productsListBackup = listOf<Product>()
interface OnProductClickListener {
//Método para gestionar el OnClick de los items del recyclerview
fun onProductClick(product: Product)
//Método para gestionar el click largo cuando se toca el item por unos segundos..
fun onProductLongClick(product: Product, position: Int)
}
fun setProductList(productsList: List<Product>) {
this.productsList = productsList
this.productsListBackup = productsList
notifyDataSetChanged()
}
fun getProductList():List<Product>{
return this.productsList
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> {
val itemBinding = ProductsListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val holder = MainViewHolder (itemBinding)
holder.itemView.setOnClickListener {
val position = holder.adapterPosition.takeIf { it != DiffUtil.DiffResult.NO_POSITION }
?: return@setOnClickListener
itemClickListener.onProductClick(productsList[position])
}
holder.itemView.setOnLongClickListener {
val position = holder.adapterPosition.takeIf { it != NO_POSITION }
?: return@setOnLongClickListener true
itemClickListener.onProductLongClick(productsList[position], position)
return@setOnLongClickListener true
}
return holder
}
override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
when (holder) {
is MainViewHolder -> holder.bind(productsList[position])
}
}
override fun getItemCount(): Int = productsList.size
private inner class MainViewHolder (val binding: ProductsListBinding) : BaseViewHolder<Product>(binding.root) {
override fun bind(item: Product) {
val description = if (item.description.isNotEmpty()) item.description else "Sin descripción."
val barcode = if (item.barcode.isNotEmpty()) item.barcode else "Sin código."
binding.txtName.text=item.name
binding.txtDescription.text=description
binding.txtBarcode.text=barcode
binding.txtQty.text = "Cantidad: ${item.qty}"
binding.txtPrice.text = "S/${item.price}"
//Si el image_bitmap no es nulo:
item.image_bitmap?.let { binding.productImage.setImageBitmap(item.image_bitmap!!) }
}
}
//Filterable methods to search
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(charSequence: CharSequence?): Filter.FilterResults {
val queryString = charSequence?.toString()?.lowercase()
val filterResults = Filter.FilterResults()
filterResults.values = if (queryString==null || queryString.isEmpty())
productsList
else
productsList.filter {
it.name.lowercase().contains(queryString) ||
it.barcode.lowercase().contains(queryString) ||
it.description.lowercase().contains(queryString)
}
return filterResults
}
override fun publishResults(charSequence: CharSequence?, filterResults: Filter.FilterResults) {
productsList = filterResults.values as List<Product>
notifyDataSetChanged()
}
}
}
}
為了尋找我正在使用一個SearchView:
private fun setupSearchView(){
binding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
productsRecyclerViewAdapterV2.filter.filter(query)
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
productsRecyclerViewAdapterV2.filter.filter(newText!!)
return false
}
})
}
然而,搜索任務在開始時運行良好,但在搜索完某些內容后,整個productList內容都已更新,現在資料比以前少了,當我輸入內容然后洗掉一些單詞時,我可以看到這種罕見的行為--The list has now less data--
例子:
初始名單:

搜索東西:

現在我洗掉整個文本searchView:

我們可以看到recyclerview并沒有用原始資料更新,現在只有之前搜索的item。
我想改進getFilter()recyclerview 配接器的功能,因為我認為存在問題或者可能在方法內部publishResults()。
任何想法的人來解決這個問題,我將不勝感激。提前致謝。
uj5u.com熱心網友回復:
您已經有一個備份串列,這很好,但是您需要使用該備份串列作為完整專案串列的來源,否則您的過濾器將繼續過濾其先前的輸出而不是原始完整專案串列。
另外,一個小費。用于String?.orEmpty()避免不必要地處理可空值。
override fun performFiltering(charSequence: CharSequence?): Filter.FilterResults {
val queryString = charSequence?.toString().orEmpty().lowercase()
return Filter.FilterResults().apply {
values = when {
queryString.isEmpty() -> productsListBackup
else -> productsListBackup.filter {
it.name.lowercase().contains(queryString) ||
it.barcode.lowercase().contains(queryString) ||
it.description.lowercase().contains(queryString)
}
}
}
旁注:在 Kotlin 中,您不應該創建get...()和set...()函式。你已經有了屬性,所以 getter 和 setter 是隱式的。如果您需要做任何復雜的事情,您可以定義自定義的 getter 或 setter 行為。因此,在您的情況下,您可以洗掉getProductList()并setProductList()更新您現有的屬性以公開,如下所示:
var productsList = listOf<Product>()
set(value) {
field = value
productsListBackup = productsList
notifyDataSetChanged()
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/430318.html
