写一个合适好用的SharedPreferences工具类

  • A+
所属分类:Android

在Android开发中,SharedPreferences大概是我们常用的最简单的一种键值对(Key-Value)数据存储方式了,任何一个Android开发者都几乎不可能完全不用SharedPreferences。而它的使用确实很简单,不需要去自己操作读写文件,也不需要去写SQLite数据库,只是简单的put/get操作而已。但是,你的使用方法真的科学合理吗?

原始而古老的SharedPreferences使用方法

不经过任何封装的话,原始的SharedPreferences使用起来大概是这样子的:

单纯的看这么一小段代码,似乎不觉得有什么问题,而且用起来确实能得到想要的结果。但如果一个项目里,到处是这样的代码,甚至一个Activity里都有许多这样的地方,那就非常难看了,我说的难看,相信大家都理解是什么意思。所以,我们有必要进行一下封装,写一个SharedPreferences工具类,这样读写数据就不用这么“大张旗鼓”了。

如何设计一个好用的SharedPreferences工具类?

一个好用的SharedPreferences工具类,一般要满足这么几个条件才算是合格的:

  • 不需要每次使用都去获取SharedPreferences的实例。getSharedPreferences这个方法,调用一次就可以了。
  • 最好不需要获取SharedPreferences.Editor实例,也不需要调用什么commit、apply等方法,直接通过put/get来进行读写。
  • 最好能实现一些数据异常处理,如传入的key是null,或者传入的value不符合实际需求等情况下,能有一定的处理。
  • 能够保存对象数据,如List和Map这些常用的数据结构,尤其是Json形式的数据。

根据这几个条件,我们已经可以初步写出一个SharedPreferencesUtils工具类了:

这里我通过Gson来实现对象与字符串的互转,从而实现了对象的数据保存。也因此,没有额外写putStringSet与getStringSet方法,因为直接将Set<String>作为对象来处理就足够了。

SharedPreferences的Key值该如何处理?

刚才写的工具类,使用起来基本上没有问题了。但实际上还存在一个非常现实的问题:各种Key值该怎么处理(或者说如何保存)?

有的人可能不太理解这个问题的含义,说白了,我们通过SharedPreferences保存的数据是持久化的,无论是保存还是读取,都依赖于那个String型的Key,而这个Key该如何保存,就很值得我们思考了。通常这些Key值可以认定为常量(偶尔个别的Key除了原来的字符串,还会带点别的东西如版本号等)。

很多开发习惯很差的同学,Key都是随遇而安的,如直接使用这样的代码:

这样做的结果就是,用不了多久他就可能会忘了很多东西,如果在别的页面还要读写该Key的时候,要么全局搜索该Key,要么就出错:是nickname?还是Nickname?还是NickName?这样做的人,绝对不是一个合格的开发者。

所以有经验的同学,都知道最好把SharedPreferences所使用的所有Key,都保存在一起,有新的Key就添加一下,如此显得十分干净简练,不容易出错。是的,这样做确实是对的,也是应该的,但实际上还存在一个问题:你能记得每个Key对应的value类型吗?尤其是,团队开发,有的值是整个App里很多页面都会用到的,你保存的这个值,其他同事知道该怎么读取吗?总不能,我们每添加一个Key,就要去通知所有人吧?不现实,实际上大家很可能也会因为忙碌而忽略你的消息。

那给每个常量再添加一个注释怎么样?例如这样的:

看起来问题解决了,但大部分人的习惯恐怕不太容易改,注释写得再好也得有人看啊。相信Key值一多,团队里就会有人不太注意到这些注释了,所以这种方法可行,但对开发人员无法形成强力的约束,最终效果要看团队的整体素质。

那么有没有更强力一点的约束呢?办法当然是有的,那就是整个工具类对外只暴露set/get方法,连字符串常量也不对外暴露,约束团队使用SharedPreferences必须通过工具类,就这么简单:

在这段代码里,只写了一个常量TEST_SCORE,即考试分数。在它的set方法里,会对给定值进行一次判断,因为你一定知道它的取值范围是多少(我这里写成了0到100),所以当遇到一些非法值时就可以直接改成一个默认的值。而get方法直接表明了该Key对应的value是整数型的,避免了因数据类型弄混导致的各种异常。

也许有人会问:这样做会不会导致这个工具类代码特别多?实际上这是一个见仁见智的问题,的确,每个Key键除了一个常量外,还多了一个set方法和一个get方法,看起来繁琐,但带来的好处是所有成员都能对此清晰明了,不容易出错,相比较之下的缺点基本可以忽略了。也有人认为这样会让APK包的方法数增加,但现实情况是一个有一定规模的App已经完全不可能将方法数控制在64K之内了,我觉得这已经不是一个需要太过于操心的问题了。

KaelLi

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: