为了账号安全,请及时绑定邮箱和手机立即绑定

Android 开发之 SharedPreferences 小坑

标签:
Android
小序

做过 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);
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
8801
获赞与收藏
71

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消