RecyclerView:检测到不一致.无效的项位置-使用getFilter()



我有一个带有国家列表的Recycler视图。在Recycler的顶部还有一个搜索视图,用于过滤国家和地区,无需滚动长列表即可查找。当我在搜索中输入并平行滚动列表时,有时会出现检测到不一致的错误。

Fatal Exception: java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionCountryHolder{a35d5ed position=54 id=-1, oldPos=-1, pLpos:-1 no parent} androidx.recyclerview.widget.RecyclerView{1c30d63 VFED..... ......ID 0,410-1440,1899 #7f0a0028 app:id/SymbolRecyclerView}... androidx.recyclerview.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5974)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6158)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)

或者这个:

Fatal Exception: java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 14(offset:14).state:48 androidx.recyclerview.widget.RecyclerView{6df376e VFED..... ........ 0,410-1440,1899 #7f0a0028 app:id/SymbolRecyclerView}....
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:345)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)

或者在GooglePLay测试中这样:

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView{5ae0fff VFED..... ......ID 0,322-1080,1561 #7f0a0028 app:id/SymbolRecyclerView}....
at androidx.recyclerview.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:3051)
at androidx.recyclerview.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:5536)
at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:12253)
at androidx.recyclerview.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:7354)
at RecyclerView_Adapter$getFilter$1.publishResults(RecyclerView_Adapter.kt:109)

我在谷歌上搜索了一下,发现我需要使用notifyDataSetChanged((函数,并在搜索时使用临时列表进行修改,但这在我的代码中似乎是正确的。有人能帮忙修理吗?下面是我的RecyclerView_Adapter代码:

class RecyclerView_Adapter(private var countryList: ArrayList<String>) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), Filterable {
var countryFilterList = ArrayList<String>()
lateinit var mcontext: Context
class CountryHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
init {
countryFilterList = countryList
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val countryListView =
LayoutInflater.from(parent.context).inflate(R.layout.custom_list_row, parent, false)
val sch = CountryHolder(countryListView)
mcontext = parent.context
return sch
}
override fun getItemCount(): Int {
return countryFilterList.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemView.Symbol.text = countryFilterList[position]
}

override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val charSearch = constraint.toString()
if (charSearch.isEmpty()) {
countryFilterList = countryList
} else {
val resultList1 = ArrayList<String>()
for (row in countryList) {
if (row.contains(charSearch)) {
resultList1.add(row)
}
}
countryFilterList = ArrayList(resultList1.distinct())
}
val filterResults = FilterResults()
filterResults.values = countryFilterList
return filterResults
}
@Suppress("UNCHECKED_CAST")
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
countryFilterList = results?.values as ArrayList<String>
notifyDataSetChanged()
}
}
}

请尝试此替代解决方案。

从原始列表创建可流动

val countryListFlowable = Flowable.fromArray(countryList)
val consumer = Consumer<ArrayList<String>> {
//Here Search result will come as it
mAdapterRecycleView.updateList(it)
}
val disposableSearch = countryListFlowable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).map { t: ArrayList<String> ->
t.filter {countryName: String ->
var isFound=false
if (countryName.contains(charSearch)) {
isFound = true
}
isFound
}
}.subscribe(consumer)

您的适配器将具有此方法

fun updateList(list: ArrayList<String):  {
countryFilterList = list
notifyDataSetChanged()
}

最新更新