RecyclerView条目选中状态在应用前后台切换后异常消失求助
问题分析与解决方案
核心问题原因
- 应用最小化恢复后,
ImageFragment的onStart方法会重新调用accessStatusesFolder(),该方法会重新创建所有WhatsAppStatus对象,导致适配器中selectedItems列表里的旧对象,和新加载的列表对象不是同一个实例,选中状态的标记自然无法匹配显示。 onBindViewHolder中注释掉了notifyItemChanged(position),点击条目后无法及时通知UI更新,加剧了状态显示异常。setColorFilter(R.color.black)写法错误:该方法需要传入颜色值(ColorInt),而非颜色资源ID,会导致颜色滤镜无法正确生效。
修复步骤
1. 给WhatsAppStatus添加唯一标识
为每个状态条目添加唯一ID,用来匹配应用恢复前后的同一文件:
data class WhatsAppStatus(val documentFile: DocumentFile) { var isSelected: Boolean = false // 用文件URI作为唯一标识 val uniqueId: String get() = documentFile.uri.toString() }
2. 保存并恢复选中状态
在ImageFragment中维护选中条目的唯一ID集合,应用恢复时根据ID重新匹配设置选中状态:
class ImageFragment : Fragment(), ImageAdapter.RecyclerViewSelectionListener, ImageAdapterListener { // 保存选中条目的唯一ID集合 private val selectedItemIds = mutableSetOf<String>() // ...其他原有代码 override fun onItemSelected(selectedStatus: WhatsAppStatus, size: Int) { (activity as StickerActivity).onItemSelected(selectedStatus, size) // 更新选中ID集合 if (selectedStatus.isSelected) { selectedItemIds.add(selectedStatus.uniqueId) } else { selectedItemIds.remove(selectedStatus.uniqueId) } } // 修改适配器数据更新逻辑,恢复选中状态 override fun notifyAdapterDataSetChanged(fragment: ImageFragment) { val adapter = recyclerView.adapter as ImageAdapter adapter.clearSelected() // 根据保存的ID匹配新加载的条目,恢复选中状态 imageFile.forEach { item -> if (selectedItemIds.contains(item.uniqueId)) { item.isSelected = true adapter.selectedItems.add(item) } } adapter.notifyDataSetChanged() } }
3. 修复适配器中的UI更新与颜色滤镜问题
修改ImageAdapter的onBindViewHolder方法,补全UI更新通知,修正颜色滤镜的错误写法:
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) { val currentItem = file[position] val blackColor = ContextCompat.getColor(context, R.color.black) if (currentItem.isSelected) { holder.image.setColorFilter(blackColor) holder.checkBox.visibility = View.VISIBLE } else { holder.image.clearColorFilter() holder.checkBox.visibility = View.GONE } Glide.with(context).load(currentItem.documentFile.uri).into(holder.image) holder.image.setOnClickListener { currentItem.isSelected = !currentItem.isSelected if (currentItem.isSelected) { holder.image.setColorFilter(blackColor) holder.checkBox.visibility = View.VISIBLE selectedItems.add(currentItem) } else { holder.image.clearColorFilter() holder.checkBox.visibility = View.GONE selectedItems.remove(currentItem) } listener.onItemSelected(currentItem, selectedItems.size) // 必须通知条目更新,确保UI及时刷新 notifyItemChanged(position) } }
4. 可选:持久化选中状态
如果需要应用完全退出后再打开也保留选中状态,可以在onPause时将selectedItemIds保存到SharedPreferences,onStart时再读取恢复:
// 保存选中ID override fun onPause() { super.onPause() val prefs = requireContext().getSharedPreferences("StatusPrefs", Context.MODE_PRIVATE) prefs.edit().putStringSet("selectedIds", selectedItemIds).apply() } // 恢复选中ID override fun onStart() { super.onStart() val prefs = requireContext().getSharedPreferences("StatusPrefs", Context.MODE_PRIVATE) prefs.getStringSet("selectedIds", mutableSetOf())?.let { selectedItemIds.clear() selectedItemIds.addAll(it) } // ...其他原有代码 }
内容的提问来源于stack exchange,提问作者Danish
相关产品推荐
相关产品推荐

