继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android 开发之 SharedPreferences 小坑

单刀土豆
关注TA
已关注
手记 26
粉丝 8801
获赞 71
小序

做过 Android 开发的对 SharedPreferences 应该是再熟悉不过了,除非你只写过小 Demo,否则不可能没用过 SharedPreferences,不过今天我还真被 SharedPreferences 小坑了一把。

起因

有个应用添加白名单需求,说白了就是保存一个包名的 Set,当时一想简单的需求没必要存在数据库里,存在 SharedPreferences 中最合适不过了,因为 SharedPreferences 提供 getStringSetputStringSet 接口,简直量身定制。于是把白名单包名的 Set 直接通过 putStringSet 存进 SharedPreferences,需要的时候再通过 getStringSet 读取出来,一切都是那么的迅速和顺利。

经过

当白名单需要更新时,我大概是这么实现的:

Set whiteList = config.getStringSet(Config.KEY_CLEAN_WHITELIST);
if (checkBox.isChecked()) {
  whiteList.add(runningApp.pkgName);
} else {
  whiteList.remove(runningApp.pkgName);
}
config.putStringSet(Config.KEY_CLEAN_WHITELIST, whiteList);

看过代码之后你有没有发现什么问题,如果没有那么恭喜你,你也入坑了!不过看没看出来都没关系,谁没踩过坑。好了,不卖关子了,上面的代码是无法正确更新 SharedPreferences 中的 Set 字段的,为什么?先看下官方 API 吧。

// getStringSet Added in API level 11
Set getStringSet (String key, Set defValues)

// Retrieve a set of String values from the preferences.

// Note that you must not modify the set instance returned by this call. The consistency of the stored data is not guaranteed if you do, nor is your ability to modify the instance at all.

看到最后一段的 Note 没,『一定不要修改 getStringSet 的返回值,否则不能保证数据的一致性,而且你也没有能力去修改』,问题就出在这里了。

结果

知道问题所在当然就很好解决了,做一层额外的浅拷贝,然后对拷贝后的 Set 进行修改,再把结果通过 putStringSet 写回到 SharedPreferences 就 OK 了。

Set whiteList = config.getStringSet(Config.KEY_CLEAN_WHITELIST);
Set result = new HashSet<>(whiteList);
if (checkBox.isChecked()) {
  result.add(runningApp.pkgName);
} else {
  result.remove(runningApp.pkgName);
}
config.putStringSet(Config.KEY_CLEAN_WHITELIST, result);
打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP

热门评论

哈哈,学习了 看来看方法说明很重要?

查看全部评论