java .lang.IndexOutOfBoundsException: обнаружено несоответствие. Неверный адаптер держателя вида при использовании DiffUtil - PullRequest
1 голос
/ 19 февраля 2020

Ниже приведен класс адаптера для загрузки всех элементов книги в режиме утилизации. Использовал DiffUtils, чтобы весь список не получал уведомления.


class BooksAdapter(var mContext: Context) : RecyclerView.Adapter<BooksAdapter.BooksViewHolder>() {

    var books: List<BookTable> = ArrayList()
        set(value) {
            val result = DiffUtil.calculateDiff(BookListDiffCallBacks(ArrayList(value), ArrayList(books)))
            field = value
            result.dispatchUpdatesTo(this)
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BooksViewHolder {
        val binding = DataBindingUtil.inflate<ItemBookBinding>(LayoutInflater.from(mContext), R.layout.item_book, parent, false)
        return BooksViewHolder(binding)
    }

    override fun getItemCount(): Int {
        return books.size
    }

    override fun onBindViewHolder(holder: BooksViewHolder, position: Int) {
        holder.setData(books[position])
    }

    inner class BooksViewHolder(var binding: ItemBookBinding) : RecyclerView.ViewHolder(binding.root) {
        fun setData(bookTable: BookTable) {
            binding.book = bookTable
        }
    }
}

Мой класс DiffUtil такой, как показано ниже. Я расширил класс DiffUtil и проверил, являются ли элементы одинаковыми или нет, если нет, то DiffUtil будет обрабатывать обновление

class BookListDiffCallBacks(var oldBooks: ArrayList<BookTable>, var newBooks: ArrayList<BookTable>) : DiffUtil.Callback() {

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldBooks[oldItemPosition].bookId == newBooks[newItemPosition].bookId
    }

    override fun getOldListSize(): Int {
        return oldBooks.size
    }

    override fun getNewListSize(): Int {
        return newBooks.size
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldBooks[oldItemPosition] == newBooks[newItemPosition]// == means structural equality checks in kotlin
    }

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        return super.getChangePayload(oldItemPosition, newItemPosition)
    }
}

Класс модели



@Entity(
    tableName = "book_table"//,
//    foreignKeys = [ForeignKey(entity = CategoryTable::class, parentColumns = arrayOf("categoryId"), childColumns = arrayOf("categoryId"), onDelete = ForeignKey.CASCADE)]
)
class BookTable : BaseObservable() {

    @Bindable
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "bookId")
    var bookId: Int = 0
        set(value) {
            field = value
            notifyPropertyChanged(BR.bookId)
        }

    @Bindable
    var name: String? = null
        set(value) {
            field = value
            notifyPropertyChanged(BR.name)
        }

    @Bindable
    var categoryId: Int? = null
        set(value) {
            field = value
            notifyPropertyChanged(BR.categoryId)
        }

    override fun equals(other: Any?): Boolean {

        if (other === this) return true // means same reference
        if (other !is BookTable) return false// is not of same class

        // other is now Booktable instance as above condition false if you remove that condition then it will show error in below condition
        // as it has passed above condition means it is of type BookTable
        return (bookId == other.bookId
                && categoryId == other.categoryId
                && name == other.name)

    }

    override fun hashCode(): Int {
        var result = bookId
        result = 31 * result + (name?.hashCode() ?: 0)
        result = 31 * result + (categoryId ?: 0)
        return result
    }

}

Мое приложение получает cra sh, и я получаю эту ошибку:

java .lang.IndexOutOfBoundsException: обнаружено несоответствие. Недопустимое положение адаптера держателя вида BookBookViewHolder

Я реализовал класс DiffUtil, чтобы элементы представления полного повторного просмотра не получали уведомление.

Ссылка: https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/DiffUtil

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Иногда эта ошибка может сохраняться, если я нашел обходной путь. Спасибо, Райан за ценные усилия. На самом деле ваше решение решило мою проблему, ниже приведено предупреждение.

class WrapContentLinearLayoutManager : LinearLayoutManager {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}

    override fun onLayoutChildren(recycler: Recycler, state: RecyclerView.State) {
        try {
            super.onLayoutChildren(recycler, state)
        } catch (e: IndexOutOfBoundsException) {
            Log.e("Error", "IndexOutOfBoundsException in RecyclerView happens")
        }
    }
}
1 голос
/ 19 февраля 2020

Ваши параметры для конструктора BookListDiffCallBacks обратные:

val result = DiffUtil.calculateDiff(BookListDiffCallBacks(ArrayList(value), ArrayList(books)))

Вы передаете new, old, но конструктор ожидает old, new.

...