Android ViewPager2删除条目时移除页面错误问题求解
问题原因
FragmentStateAdapter默认以条目位置作为唯一标识判断Fragment是否需要更新,当你删除某位置的条目后,后续条目的位置整体前移,但Adapter默认逻辑会认为后续条目没有发生变化,导致视图和数据绑定错位,就会出现删当前页却移除了下一页的问题。
修复方案
1. 重写唯一标识判断方法
给你的ShapePagerAdapter新增getItemId和containsItem两个方法,使用业务唯一的shapeId作为条目唯一标识,替代默认的位置标识:
override fun getItemId(position: Int): Long { // 用shapeId的哈希值作为唯一ID,普通场景下足够使用 return shapeIds!![position].hashCode().toLong() } override fun containsItem(itemId: Long): Boolean { return shapeIds?.any { it.hashCode().toLong() == itemId } ?: false }
2. 新增删除后的页面跳转逻辑
你当前只更新了适配器数据,没有手动控制ViewPager2的跳转,需要在removeItem方法中增加页面切换逻辑,满足你的跳转需求:
fun removeItem(activity: AppCompatActivity, viewPager: ViewPager2, position: Int) { try { // 先校验参数合法性 shapeIds ?: return if (position < 0 || position >= shapeIds!!.size) return // 移除数据库数据 dbManager.deleteShape(shapeIds!![position]) // 移除列表数据 shapeIds!!.removeAt(position) // 通知适配器更新 notifyItemRemoved(position) if (itemCount == 0) { activity.finish() return } // 计算跳转位置:如果删除的是原来的最后一页,跳转到新的最后一页,否则跳转到当前位置(即原下一页) val targetPosition = if (position >= itemCount) itemCount - 1 else position viewPager.setCurrentItem(targetPosition, false) } catch (e: DatabaseAccessException) { // ... } }
如果你不想把ViewPager传到适配器里,也可以在调用removeItem的上层逻辑(比如Activity/Fragment中)执行页面跳转即可。
3. 可选优化:空安全优化
把shapeIds改为非空类型,避免空指针风险:
// 把原来的private var shapeIds: MutableList<String>? = null 替换为 private var shapeIds: MutableList<String> = mutableListOf() // 初始化的时候直接赋值 init { dbManager = DatabaseManager(activity) try { shapeIds = dbManager.getShapeIds().toMutableList() } catch (e: DatabaseAccessException) { // ... } }
改完之后就可以移除所有shapeIds!!的非空断言,代码更简洁安全。
修复后效果
- 删除任意条目时,对应页面会被正确移除,自动跳转到原列表的下一个页面
- 删除最后一个条目时,自动跳转到新的最后一页
- 删除最后一条数据时,Activity正常关闭
内容的提问来源于stack exchange,提问作者user3386180
相关产品推荐
相关产品推荐

