You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android SharedPreferences存储列表被覆盖无法追加更新问题

SharedPreferences存储ArrayList每次写入覆盖旧数据问题修复

问题本质

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 04:12:56