Android SharedPreferences存储列表被覆盖无法追加更新问题
问题本质
SharedPreferences没有针对单key的增量追加API,所有写入操作都是全量覆盖对应key的存储值。你当前的写入逻辑直接使用内存中持有的exerciseList写入,这个列表会在页面重建、组件重新初始化时被重置,没有合并之前已经持久化的历史记录,所以每次写完只剩最新一次的测验记录。
定位到的代码问题
- 写入环节:
saveScores方法中直接往当前内存里的exerciseList添加本次记录就写入,没有先读取SP中已存的历史数据做合并 - 上下文使用不规范:Fragment中直接用
context as Activity强转获取上下文,页面销毁时容易触发崩溃 - 适配器刷新逻辑冗余:全量替换列表数据后只需要调用
notifyDataSetChanged即可,不需要额外调用notifyItemInserted
修复步骤
- 改写分数存储逻辑,写入前先拉取已存的历史记录合并后再写回
private fun saveScores(correctAnswers: Int, totalQues: Int) { // 读取SP中已持久化的历史记录,读取失败则初始化空列表 val historyList = session.readListFromPref(requireContext()) as? ArrayList<Exercise> ?: arrayListOf() // 追加本次测验记录 historyList.add(Exercise(topicName, correctAnswers.toString(), totalQues.toString())) // 更新内存中的列表、刷新适配器 exerciseList = historyList adapter.setExList(exerciseList) adapter.notifyDataSetChanged() // 将合并后的完整列表写入SP,完成持久化 session.writeListInPref(requireContext(), exerciseList) Log.d("veg", exerciseList.toString()) }
- 修正Fragment中读取历史列表的逻辑,去掉冗余刷新和不安全的强转
val historyList = session.readListFromPref(requireContext()) as? ArrayList<Exercise> ?: arrayListOf() if (historyList.isNotEmpty()) { adapter.setExList(historyList) adapter.notifyDataSetChanged() } else { Toast.makeText(requireContext(), "No quiz attempted yet", Toast.LENGTH_SHORT).show() }
- 确认适配器
setExList方法实现正确,避免列表替换异常
// 适配器内setExList参考实现 fun setExList(newList: List<Exercise>) { // 清空旧数据再追加新数据,不要直接替换内部列表引用 exerciseList.clear() exerciseList.addAll(newList) }
注意:如果你的
writeListInPref和readListFromPref是通过Gson序列化/反序列化列表实现的,要保证Exercise类已经正确实现了序列化逻辑,避免读写时数据丢失。
内容的提问来源于stack exchange,提问作者Ali Zain
相关产品推荐
相关产品推荐

