原文发布在个人简书,更多内容欢迎关注笔者简书 ,评论、互相交流请到简书,谢谢!
现在许多主流的App都会做离线缓存
功能,比如“今日头条”,“新浪微博”,每次启动项目或者刷新有网络时都是获取网络数据,网络出错时会展示缓存数据提高用户体验。
笔者就结合之前见过的、以及笔者自己做缓存的方式,谈一谈离线缓存的实现方案以及其中的优缺点。“今日头条”,“新浪微博”都是缓存了第一页的数据,笔者这里也是这样。
无demo不文章,笔者已将demo1 和demo2 写好,欢迎下载.
缓存数据的方式一般有以下几种:
由于这里缓存相对大量的数据,采用sqllite数据库来实现离线缓存。
通过下面几个问题来讲述离线缓存的过程
有的朋友在做缓存的时候,会这样设计sql语句
上面的方式设计sql语句,看上去明显很繁琐,涉及到的字段很多也容易混乱。笔者不会采用这样方式设计sql,而是像下面这种方式去设计sql
上面的sql语句很明显避免了那么多字段的干扰。不论是以 JSON数据格式
还是模型数据格式
,笔者会将数据已二进制的方式存入数据库(BLOB是数据库中用来存储二进制文件的字段类型)
有人喜欢缓存模型(model)->转换成二进制数据->存入数据库
但是缓存模型的过程需要模型实现NSCoding协议并进行coder和encoder
,如果采用了像YYModel或者MJExtension这样的第三方库,实现coder和encoder
还相对方便一些,但是如果是自己实现这个过程还是有些繁琐的过程。
所以,笔者采用JSON格式数据->转换成二进制数据->缓存数据库,在iOS中不必缓存JSON格式的字符串,而是直接缓存字典就可以,因为字典就是符合JSON格式的数据。不论是字典还是模型数据都是先转换成二进制数据,再将二进制数据存入数据库。
下面来说一下cache_key的格式,笔者这里采用的是网络接口请求的url+请求参数
拼接组成一个完整的字符串
来作为cache_key。
为什么采用URL+参数
的方式作为cache_key那?
因为URL+参数
可以区分接口的唯一性,因为做网络请求时知道了url和请求参数就知道了要请求哪个接口。
笔者这里只设计了T_CACHE
一张表,所有的数据缓存都存放在这一张表里,所以需要一个区分缓存数据的唯一标识,通过这个唯一标识我们就知道要获取的首页数据的缓存、还是其他什么页的缓存。显然URL+参数
作为这个唯一标识很合适,采用URL+参数
的方式通用性也很强,我们拿到其他项目也适用。因为不论什么项目几乎都是通过URL+参数
方式进行接口请求。
针对缓存数据的设计方案,各位可以说是各显神通。
有人会针对每一个要进行离线缓存的接口设计一套sql语句和缓存类进行数据的存取,也有人会像下面的设计方式进行数据存取。
笔者离线缓存思路如下:
为什么会采用上面的缓存方案那?
因为我们在实际项目开发中,有时候在项目最开始我们并不是很清楚要不要做离线缓存功能的。有时候情况会是这样的,项目已经维护了几个版本了,产品经理某一天突然告诉你XXX界面显示不友好,加上离线缓存功能吧;也有可能你之前的项目经过了好几手,里面有之前的开发人员设计的缓存方案,而每种方案又都不一样。这时采用笔者这种方案是在现有项目基础上,以最小的改动实现离线缓存的一种方式。当然,应该还会有更好的方式吧,如果大家有其他好的方式,非常非常欢迎指点交流。
下面对笔者的缓存方案进行详细讲解
首先先说一下网络层的一个小设计点,有的人会像下面的设计方式进行网络层API的请求。
有一个APIRequest统一处理所有的网络请求,每个接口的数据通过block或者是delegate等方式返回去。如果是通过这种方案进行的网络请求,那么就可以通过下面的方式进行离线缓存。
说明:
这里需要对isCache666
这个参数进行一下说明,因为我们并不需要对所有的接口请求做离线缓存,可能是针对某些接口数据做缓存,那此时我们就需要区分哪些接口要做缓存、哪些不需要做缓存。为了实现这个区分,我们手动的添加了一个isCache666
这样一个参数,这里为了直观,就传了一个YES,其实传什么数据都可以,因为在下面判断的时候只是判断cacheKey这个字符串中是否包含isCache666
这样的子字符串(这里为了防止和后台返回的字段冲突,所以命名一些不容易冲突的名字)
针对上面的这样情况,笔者已经写好了demo1,详细的细节可以下载demo1看一下
笔者采用的网络API请求方案是这样的,每一个API对应于一个XXXAPIRequest类,然后这个XXXAPIRequest提供请求的URL和参数、请求方式、该请求是否需要进行离线缓存等信息。
说明:
所有的 XXXAPIRequest类
需要遵守APIRequestProtocol协议
,并且必须实现apiRequestURL和apiRequestParams
方法,提供请求需要的url和参数; 默认是POST请求方式,可以重写method方法来修改请求方式,同样默认isCache为NO(不进行离线缓存),如果要设置离线缓存,重写isCache方法,返回YES即可。
针对上述的缓存方案,笔者已经写好了demo2,详细的细节可以下载demo2看一下
最后
上面说的离线缓存方案是笔者个人的一些观点,当然离线缓存方案还有其他的方式,也欢迎大家交流。笔者这里也是抛砖引玉,好的方案欢迎拍过来。