Android:重启应用后SharedPreferences的getStringSet()仅返回[]或[1]
Hey,我碰到过类似的SharedPreferences问题,帮你梳理下可能的原因和解决办法~
首先得明确:SharedPreferences本身不支持直接存储集合,我们一般是把集合序列化为JSON字符串来持久化,再反序列化为集合读取。你的问题大概率出在读取逻辑的默认值处理、内存集合与持久化数据不同步,或者保存时没做持久化提交这几个点上。
1. 先检查你的存储/读取逻辑是否正确实现
给你一个标准的实现示例(用Gson做序列化,如果你用其他库逻辑类似):
正确的存储方法
// 获取SharedPreferences实例,MODE_PRIVATE保证只有你的应用能访问 val sharedPref = context.getSharedPreferences("FavoritesPrefs", Context.MODE_PRIVATE) // 要保存的String集合 val favoriteIds = listOf("id_001", "id_002", "id_003") // 把集合序列化为JSON字符串 val jsonString = Gson().toJson(favoriteIds) // 一定要调用apply()或commit()完成持久化! sharedPref.edit().putString("saved_favorite_ids", jsonString).apply()
正确的读取方法
val sharedPref = context.getSharedPreferences("FavoritesPrefs", Context.MODE_PRIVATE) // 读取时默认值设为null,而不是直接返回空数组的JSON! val savedJson = sharedPref.getString("saved_favorite_ids", null) val favoriteIds = if (savedJson != null) { // 反序列化为String集合 Gson().fromJson(savedJson, object : TypeToken<List<String>>() {}.type) } else { // 第一次启动时返回空集合,这里也可以选择把空集合写入SP(可选) emptyList<String>() }
这里的关键是:读取时不要把默认值设为"[]"(空数组的JSON),否则当SP里本来有保存的内容时,不会触发正确的反序列化逻辑。
2. 别搞混内存集合和持久化集合
很多人会在ViewModel或Activity里维护一个内存中的MutableList来操作收藏项,但容易犯一个错:重启应用后没有从SP读取数据填充这个内存集合,直接用了空的内存集合,就误以为SP里的内容丢了。
举个正确的ViewModel示例:
class FavoritesViewModel : ViewModel() { private val sharedPref = ApplicationProvider.getApplicationContext<Context>() .getSharedPreferences("FavoritesPrefs", Context.MODE_PRIVATE) // 内存中的收藏集合 val favoriteIds = mutableListOf<String>() init { // 初始化时必须先从SP加载数据填充内存集合! val savedJson = sharedPref.getString("saved_favorite_ids", null) savedJson?.let { val savedList = Gson().fromJson(it, object : TypeToken<List<String>>() {}.type) favoriteIds.addAll(savedList) } } // 保存时把内存集合同步到SP fun saveFavorites() { val jsonString = Gson().toJson(favoriteIds) sharedPref.edit().putString("saved_favorite_ids", jsonString).apply() } }
这样重启后,内存集合会自动从SP加载之前保存的内容,不会变成空数组,除非SP里确实没有任何数据。
3. 确认保存时执行了持久化提交
一定要记住:调用edit().putString(...)之后,必须调用apply()或者commit()才能把修改写入磁盘。如果漏了这一步,修改只会停留在内存里,重启后就会丢失。
❌ 错误示例(没提交):
sharedPref.edit().putString("saved_favorite_ids", jsonString)
✅ 正确示例:
// 推荐用apply(),异步提交不阻塞主线程 sharedPref.edit().putString("saved_favorite_ids", jsonString).apply() // 或者用commit(),同步提交(会阻塞线程,不建议在主线程使用) sharedPref.edit().putString("saved_favorite_ids", jsonString).commit()
4. 排查是否有意外清除SP的操作
检查你的代码里有没有调用sharedPref.edit().clear()或者sharedPref.edit().remove("saved_favorite_ids")的逻辑,比如在用户登出、应用退出的场景下,是不是误删了这个key的值。如果有,确认它只在真正需要清除的时候执行,而不是每次启动都触发。
按上面的步骤排查一遍,应该就能解决你的问题啦~
内容的提问来源于stack exchange,提问作者pajus_cz

