RecyclerView 和数据库 - java.lang.IndexOutOfBoundsException:检测到不一致。无效的视图持有者适配器
RecyclerView and Database - java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter
可以删除添加到数据库中的第一个项目(最旧的项目),但是当我尝试从中间删除一个项目或添加到数据库中的最新项目时,会出现以下错误。 deletePlayerHistory()
已调用函数以从数据库中删除项目。
如下图:
项目 1(数据库中添加的最新项目)-> 错误
项目 2 -> 错误
项目 3 -> 错误
ITEM 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
}
好的,我得到答案了
在 FriendHistoryAdapter.kt
class 和 deletePlayerHistory()
函数调用 notifyItemRemoved(position)
和 notifyItemRangeChanged(position,friendHistoryData.size)
中的 init
块中使用 notifyDataSetChanged()
来更新最终列表的范围。这就是更新包含数据库中项目的列表的大小的问题。
可以删除添加到数据库中的第一个项目(最旧的项目),但是当我尝试从中间删除一个项目或添加到数据库中的最新项目时,会出现以下错误。 deletePlayerHistory()
已调用函数以从数据库中删除项目。
如下图:
项目 1(数据库中添加的最新项目)-> 错误
项目 2 -> 错误
项目 3 -> 错误
ITEM 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
}
好的,我得到答案了
在 FriendHistoryAdapter.kt
class 和 deletePlayerHistory()
函数调用 notifyItemRemoved(position)
和 notifyItemRangeChanged(position,friendHistoryData.size)
中的 init
块中使用 notifyDataSetChanged()
来更新最终列表的范围。这就是更新包含数据库中项目的列表的大小的问题。