Renew StableIdKeyProvider cache and RecyclerView/SelectionTracker crash on new selection after item removed
I am ended up to play with StableIdKeyProvider
and switch to plain my own implementation of ItemKeyProvider:
new ItemKeyProvider<Long>(ItemKeyProvider.SCOPE_MAPPED) {
@Override
public Long getKey(int position) {
return adapter.getItemId(position);
}
@Override
public int getPosition(@NonNull Long key) {
RecyclerView.ViewHolder viewHolder = recyclerList.findViewHolderForItemId(key);
return viewHolder == null ? RecyclerView.NO_POSITION : viewHolder.getLayoutPosition();
}
}
Crash is gone, RecyclerView
's navigation/selection/modification looks OK.
What about StableIdKeyProvider
?.. Hmm, may be it is not designed to work with mutable content of RecyclerView
.
My problem was solved by setting setHasStableIds(true)
in Recycle view adapter and overriding getItemId
, It seems that Tracker require both setHasStableIds(true)
and overrindinggetItemId
in adapter I got this error after setting stable Ids true without overriding getItemId
init {
setHasStableIds(true)
}
override fun getItemId(position: Int) = position.toLong()
override fun getItemViewType(position: Int) = position
I encountered the same issue with the StableIdKeyProvider. Writing a custom implementation of ItemKeyProvider seems to do the trick. Here's a basic Kotlin implementation you can use when building a selection tracker for a RecyclerView:
class RecyclerViewIdKeyProvider(private val recyclerView: RecyclerView)
: ItemKeyProvider<Long>(ItemKeyProvider.SCOPE_MAPPED) {
override fun getKey(position: Int): Long? {
return recyclerView.adapter?.getItemId(position)
?: throw IllegalStateException("RecyclerView adapter is not set!")
}
override fun getPosition(key: Long): Int {
val viewHolder = recyclerView.findViewHolderForItemId(key)
return viewHolder?.layoutPosition ?: RecyclerView.NO_POSITION
}
}