Cevdam
Cevdam

Reputation: 63

SearchView not updating RecyclerView until scroll

I'm trying to filter a recyclerList that contains around 3000 items. My filter kinda works but for some reason it doesn't update the list until I scroll far enough.

For example: the top 2 elements start with the letter A --> if my filter starts with B, the top 2 elements still get shown until I scroll far enough so that they are no longer visible. When I scroll back up, they disappeared from the view.

Adapter

class LocationAdapter(
    private var locations: ArrayList<Costcenter>,
    private val onLocationClick: (location: Costcenter) -> Unit
) : RecyclerView.Adapter<LocationAdapter.LocationViewHolder>(), Filterable {

    var locationsFiltered = locations

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
        val view = LayoutInflater
            .from(parent.context)
            .inflate(R.layout.location_row, parent, false)
        return LocationViewHolder(view)
    }


    override fun getItemCount(): Int = locationsFiltered.size


    override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
        holder.bind(locationsFiltered[position])
    }


    inner class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        private val title: TextView = itemView.findViewById(R.id.txtCostCenter)
        private val desc: TextView = itemView.findViewById(R.id.txtCostCenterDescription)

        fun bind(loc: Costcenter) {
            title.text = loc.goederenontvanger
            desc.text = loc.goederenontvanger_omschrijving
            itemView.setOnClickListener {
                onLocationClick.invoke(loc)
            }
        }
    }

    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charSearch = constraint.toString()
                locationsFiltered = if (charSearch.isEmpty()) {
                    locations
                } else {
                    val resultList = ArrayList<Costcenter>()
                    for (row in locations) {
                        if (row.goederenontvanger.toLowerCase()
                                .contains(charSearch.toLowerCase()) || row.goederenontvanger_omschrijving.toLowerCase()
                                .contains(charSearch.toLowerCase())
                        ) {
                            resultList.add(row)
                        }
                    }
                    resultList
                }
                val filterResults = FilterResults()
                filterResults.values = locationsFiltered
                return filterResults
            }

            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {

            }

        }
    }
}

Fragment where the recyclerview gets created

class LocationsFragment : Fragment() {
    private lateinit var locationAdapter: LocationAdapter
    private val storageViewModel by activityViewModels<StorageViewModel>()
    private lateinit var currentView : View
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        var view = inflater.inflate(R.layout.fragment_locations, container, false)
        var recycler = view.findViewById<RecyclerView>(R.id.recyclerLocations)
        var filter = view.findViewById<SearchView>(R.id.editFilter)
        locationAdapter = LocationAdapter(Utilities.costcenters) { loc -> setSelectedLocation(loc) }
        val recycleMngr: RecyclerView.LayoutManager =
            LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)

        filter.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
            override fun onQueryTextSubmit(query: String?): Boolean {
                return false
            }

            override fun onQueryTextChange(newText: String?): Boolean {
                locationAdapter.filter.filter(newText)
                return false
            }

        })

        recycler.layoutManager = recycleMngr
        recycler.adapter = locationAdapter
        currentView = view
        return view

    }

Upvotes: 1

Views: 768

Answers (1)

Zain
Zain

Reputation: 40840

You need to update the original list locationsFiltered with the filtered results when the filter is published with publishResults() and then notifyDataSetChanged() to apply the changes on the RecyclerView

So add the below in publishResults() method:

override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
    locationsFiltered =  filterResults.values as ArrayList<Costcenter>
    notifyDataSetChanged()
}

Upvotes: 1

Related Questions