Kotlin通过SharedPreferences存储Spinner列表到RecyclerView仅获取最后选中项问题
问题根因
每次Spinner选中回调触发时,你都重新创建了一个空的ArrayList<Model>,仅将当前选中的单个条目放入列表后,直接覆盖写入SharedPreferences的对应key,之前存储的所有历史选中项都会被清空,因此最终只能读取到最后一次选中的条目。
修复实现
核心逻辑调整:写入新选中项前,先读取SharedPreferences中已经存储的历史列表,将新条目追加到列表后,再把完整的更新后列表写回存储。
修正后的Spinner选中监听代码
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(p0: AdapterView<*>?, p1: View?, position: Int, id: Long) { val gson = Gson() val listType = object : TypeToken<ArrayList<Model>>() {}.type // 1. 读取已存储的历史选中列表,无历史数据时初始化空列表 val savedJson = sharedPreferences.getString("list", null) val dataList: ArrayList<Model> = if (!savedJson.isNullOrEmpty()) { gson.fromJson(savedJson, listType) } else { arrayListOf() } // 2. 追加当前选中的条目,可按需开启去重逻辑 val currentSelected = Model(department[position]) // 若Model是data class,equals方法会自动生成,去重判断可正常生效 if (currentSelected !in dataList) { dataList.add(currentSelected) } // 3. 将更新后的完整列表重新写入SharedPreferences val updatedJson = gson.toJson(dataList) sharedPreferences.edit() .putString("list", updatedJson) .apply() // 可选:选中后立刻刷新RecyclerView展示,无需等待页面重载 (binding.recyclerView.adapter as? AddEditTextAdapter)?.apply { notifyDataSetChanged() } } override fun onNothingSelected(parent: AdapterView<*>?) { // 无选中项时无需处理 } }
优化后的列表加载逻辑
private fun initRecyclerView() { val gson = Gson() val listType = object : TypeToken<ArrayList<Model>>() {}.type val savedJson = sharedPreferences.getString("list", null) val dataList: ArrayList<Model> = if (!savedJson.isNullOrEmpty()) { gson.fromJson(savedJson, listType) } else { arrayListOf() } binding.recyclerView.layoutManager = LinearLayoutManager(this) binding.recyclerView.adapter = AddEditTextAdapter(dataList) }
注意事项
- 若你的
Model类不是Kotlindata class,需要手动重写equals()和hashCode()方法,否则列表去重判断无法正常工作 - Spinner的
onItemSelected会在控件首次加载时自动触发一次回调,若不需要初始化时自动添加默认选中项,可添加一个布尔标记位区分用户手动触发和初始化自动触发的场景 - 若需要支持删除已选中的条目,删除操作后同样要把更新后的列表重新序列化写入SharedPreferences,保证存储数据和展示数据一致
内容的提问来源于stack exchange,提问作者Khushbu
相关产品推荐
相关产品推荐

