I have a list of my data. I also have filters to choose which data in the list I want to see. By default I’m seeing all contents.
I made a RecyclerView that is well populated. The problem is about changing the list in the RecyclerView.
When I choose a filter, I’m calling getFilteredCards()
that get all content with filters applied. Then, this becomes the new list linked with the RecyclerView.Adapter
(used in getItemCount()
for example).
I’m trying to refresh the full content like that:
private fun refreshData() {
cacheFilteredCards = getFilteredCards() // get new list
notifyDataSetChanged()
}
The actual result is:
- After first filter, the first item stay in the list, all others are well removed. Then, all right ones are added.
- For the second filter (and all others after), it simply add content at bottom of the list. So I have the previous list + the new filtered one.
I tried to do:
private fun refreshData() {
cacheFilteredCards.clear()
notifyDataSetChanged()
cacheFilteredCards = getFilteredCards() // get new list
notifyDataSetChanged()
}
But the result is the same. The view isn’t fully updated that the list is newly updated with the right content.
How can I completly clear the list and keep the recyclerview? (and not make all item beeing invisible as it’s a bad solution)
Here is my full code:
fun loadList(context: Context, mainView: LinearLayout) {
val viewListener = OwnAdapter()
val spinnerLayout = LinearLayout(context)
spinnerLayout.addView(viewListener.createSpinner(context))
mainView.addView(spinnerLayout)
val view = RecyclerView(context)
view.layoutManager = LinearLayoutManager(context)
view.adapter = viewListener
view.layoutParams = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
mainView.addView(view)
}
The class OwnAdapter
:
class OwnAdapter : RecyclerView.Adapter<CardViewListener.ViewHolder>(), AdapterView.OnItemSelectedListener {
private var cacheFilteredCards = getFilteredCards()
class ViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
private fun getFilteredCards(): MutableMap<Card, Int> {
return mutableMapOf() // simplified content, in reality it's well filled according to selected item
}
fun createSeasonSpinner(context: Context): Spinner { // the spinner to select content
val data = getSpinnerData() // this is to simplify the content
val spinner = Spinner(context)
spinner.id = View.generateViewId()
spinnerId = spinner.id
spinner.setAdapter(createSpinnerAdapter(context, data)) // the listener will be this class
spinner.onItemSelectedListener = this
return spinner
}
private fun refreshData() { // refresh data
cacheFilteredCards.clear()
cacheFilteredCards.putAll(getFilteredCards())
notifyDataSetChanged()
}
override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
if(parent.id == spinnerId) {
val nextSelected = filterData[parent.getItemAtPosition(pos)]
if (nextSelected != selected) { // select new filter
selected = nextSelected
refreshData()
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LinearLayout(parent.context))
}
override fun getItemCount(): Int {
return cacheFilteredCards.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val card = cacheFilteredCards.keys.toList()[position]
// now setup the item view
}
}
2
The issue you’re facing is likely because the RecyclerView
adapter’s data list reference isn’t being properly updated, or because you’re calling notifyDataSetChanged()
in a way that doesn’t properly account for the change in the underlying list.
Try below solution
private fun refreshData() {
// Clear the existing list
cacheFilteredCards.clear()
// Add all items from the new filtered list
cacheFilteredCards.addAll(getFilteredCards())
// Notify the adapter that the dataset has changed
recyclerViewAdapter.notifyDataSetChanged()
}
1