RecyclerView и база данных — java.lang.IndexOutOfBoundsException: обнаружено несоответствие. Недопустимый адаптер держателя представления

#android #android-recyclerview #android-room #kotlin-coroutines #android-database

#Android #android-recyclerview #android-комната #kotlin-сопрограммы #android-база данных

Вопрос:

Первый элемент (самый старый элемент), добавленный в базу данных, может быть удален, но когда я пытаюсь удалить элемент из промежуточного или последнего элемента, добавленного в базу данных, возникает следующая ошибка. deletePlayerHistory() вызывается функция для удаления элемента из базы данных.
Как показано ниже:

ЭЛЕМЕНТ 1 (последний элемент, добавленный в базу данных) ->
ЭЛЕМЕНТ ошибки 2 ->
ЭЛЕМЕНТ ошибки 3 ->
ЭЛЕМЕНТ ошибки 4 (первый элемент, добавленный в базу данных) -> Может быть удален

FriendHistoryAdapter.kt

 class FriendHistoryAdapter(
    private var friendHistoryData: List<FriendHistoryData>,
    private val friendHistoryDao: FriendHistoryDao,
    private val mContext: Context
) :
    RecyclerView.Adapter<FriendHistoryAdapter.FriendHistoryHolder>(), CoroutineScope {

    private val job = Job()
    override val coroutineContext: CoroutineContext
        get() =job   Dispatchers.Main

    class FriendHistoryHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        val textViewPlayer1: TextView = itemView.findViewById(R.id.text_view_player_one_name)
        val textViewPlayer2: TextView = itemView.findViewById(R.id.text_view_player_second_name)
        val textViewScore: TextView = itemView.findViewById(R.id.text_view_score)
        val textViewWhoWon: TextView = itemView.findViewById(R.id.text_view_player_won)
        val deleteImageButton: ImageView = itemView.findViewById(R.id.image_delete)

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendHistoryHolder {
        val itemView: View = LayoutInflater.from(parent.context)
            .inflate(R.layout.friend_history_item, parent, false)
        return FriendHistoryHolder(itemView)
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: FriendHistoryHolder, position: Int) {

        holder.textViewPlayer1.text = friendHistoryData[position].playerOneName
        holder.textViewPlayer2.text = friendHistoryData[position].playerSecondName
        holder.textViewScore.text =
            "Score: ${friendHistoryData[position].playerOneScore}-${friendHistoryData[position].playerSecondScore}"
        when {
            friendHistoryData[position].playerOneScore > friendHistoryData[position].playerSecondScore ->
                holder.textViewWhoWon.text = "${friendHistoryData[position].playerOneName} won!"
            friendHistoryData[position].playerOneScore < friendHistoryData[position].playerSecondScore ->
                holder.textViewWhoWon.text =
                    "${friendHistoryData[position].playerSecondName} won!"
            else -> holder.textViewWhoWon.text = "Draw!"
        }
        holder.deleteImageButton.setOnClickListener {
            deletePlayerHistory(position)
        }
    }

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

    private fun deletePlayerHistory(position: Int) {
        val item = friendHistoryData[position]
        (friendHistoryData as MutableList).remove(item)
        launch {
            friendHistoryDao.deleteHistory(item)
            Toast.makeText(mContext, "Item removed", Toast.LENGTH_SHORT).show()
        }
        notifyItemChanged(position)
    }
}
  

VsFriendHistory.kt

 class VsFriendHistory : BaseActivity() {
    private lateinit var friendHistoryWholeData: List<FriendHistoryData>
    private lateinit var friendRecyclerView: RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_vs_friend_history)

        friendRecyclerView = findViewById(R.id.friend_recycler_view)
        friendRecyclerView.layoutManager = LinearLayoutManager(this)
        friendRecyclerView.setHasFixedSize(true)
        
        launch{
            lateinit var friendHistoryDao: FriendHistoryDao
            val database: FriendHistoryDatabase? = application?.let {
                FriendHistoryDatabase.getInstance(it)
            }
            if (database != null) {
                friendHistoryDao = database.friendHistoryDao()
            }
            friendHistoryWholeData = friendHistoryDao.getWholeHistory()
            friendRecyclerView.adapter = FriendHistoryAdapter(friendHistoryWholeData,friendHistoryDao,application)
            if (friendHistoryWholeData.isEmpty()) {
                Toast.makeText(baseContext, "No history to show", Toast.LENGTH_SHORT).show()
            }
        }
    }
}
  

FriendHistoryData.kt

 @Entity(tableName = "friend_history")
data class FriendHistoryData(
    val playerOneName: String,
    val playerSecondName: String,
    val playerOneScore: Int,
    val playerSecondScore: Int
) {
    @PrimaryKey(autoGenerate = true)
    var id = 0
}
  

Ответ №1:

Хорошо, я получил ответ
, используемый notifyDataSetChanged() в init блоке в FriendHistoryAdapter.kt классе и в deletePlayerHistory() вызове функции notifyItemRemoved(position) и notifyItemRangeChanged(position,friendHistoryData.size) для обновления диапазона конечного списка. Вот в чем проблема заключалась в обновлении размера списка, содержащего элементы в базе данных.