构建灵活的缓存机制

前言

某天,做搜索的时候,期望筛选条件的配置文件能缓存起来,不要每次都从网络获取,减少异常的发生。于是乎刷刷的开始写大量的判断逻辑if/else,做了个三级缓存,从内存、网络、本地读取数据,写完了测试也通过了,非常完美!!!

突然说要加个本地资源(asset)缓存,没问题,又加了段if/else...

哪天缓存的顺序又期望改成"网络->内存->本地->资源文件",好...改...

后来某个需求也想用缓存,但没有本地和资源文件缓存,难道又得重新来一遍,瞬间GG...

我们是不是该理一理,顺一顺,构建个灵活的缓存机制!

理一理需求

  • 需要缓存
  • 需要多级缓存
  • 需要缓存策略可变
  • 需要可以自定义缓存
  • 需要使用时候简单便捷

顺一顺实现

image.png

简要说明

  • 设计思路是工厂模式和责任链模式的结合
  • 基于RxJava的数据流
  • ICahce定义了一个getData请求方法,自定义缓存策略可以实现
  • 请求参数有ICacheParams(是否开启各级别缓存、业务参数等)
  • 默认实现了内存、网络、本地、资源Asset的缓存
    • 内存缓存利用LruCache
    • 网络缓存利用eTag
    • 本地缓存利用SP存储
    • 资源Asset缓存利用本地文件
  • 通过ICacheStrategy进行缓存策略组装,基于RxJava的error捕获,将处理转到一下个cache中进行处理
    • 默认读取策略是按序处理数据
    • 默认保存策略是全部更新

核心代码

ECache

/**
 * Created by wangpeng on 2018/7/9.
 * Cache中用到的一些key
 */
public interface ECache {

    String TAG = "Lib-Cache";

    //map中cache的key
    String CACHE_KEY = "cache_key";
    //map中内存cache的key,如没有设置会以CACHE_KEY作为key
    String MEMORY_KEY = "memory_key";
    //map中本地cache的key,如没有设置会以CACHE_KEY作为key
    String LOCAL_KEY = "local_key";
    //map中资源cache的key,如没有设置会以CACHE_KEY作为key
    String ASSET_KEY = "asset_key";
    //Context对象
    String CONTEXT_KEY = "context_key";
}

ICache

/**
 * Created by wangpeng on 2018/6/28.
 * 全局cache的协议
 */
public interface ICache<T> {

    Observable<T> getData(ICacheParams<T> cacheParams);

    void saveData(ICacheParams<T> cacheParams,T t);
}

ICacheParams

/**
 * Created by wangpeng on 2018/6/29.
 * 定义cache请求需要参数
 */
public interface ICacheParams<T> {

    /**
     * 缓存带参
     *
     * @return
     */
    Map<String, Object> getParams();

    /**
     * 获取缓存需实例化的类
     *
     * @return
     */
    Class<T> getDataClass();

    /**
     * 设置缓存时间,单位是ms
     *
     * @return
     */
    long getExpityTime();
}

ICacheStrategy

/**
 * Created by wangpeng on 2018/7/9.
 * 缓存策略
 */
public interface ICacheStrategy<T> {

    Observable<T> getDataStrategy(ICacheParams<T> cacheParams);

    void saveDataStrategy(ICacheParams<T> cacheParams,T t);

}

CacheFactory

/**
 * Created by wangpeng on 2018/6/28.
 * Cache工厂类,获取Cache数据
 * Cache的执行顺序可以自由控制
 */
public class CacheFactory<T> {

    private ICacheStrategy<T> cacheStrategy;

    public CacheFactory(ICache<T>... cacheArr) {
        this.cacheStrategy = new DefaultCacheStrategy<>(cacheArr);
    }

    public CacheFactory(ICacheStrategy<T> cacheStrategy) {
        this.cacheStrategy = cacheStrategy;
    }

    public Observable<T> getData(ICacheParams<T> cacheParams) {
        return cacheStrategy.getDataStrategy(cacheParams);
    }

    public void saveData(ICacheParams<T> cacheParams, T t) {
        cacheStrategy.saveDataStrategy(cacheParams, t);
    }
}

应用场景

  • 一些配置文件的缓存
  • 可以结合网络请求,一键缓存业务数据

如何用

Gradle依赖

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

dependencies {
    implementation 'com.github.pphdsny:cache:1.0.2.1'
    implementation 'io.reactivex:rxjava:1.2.2'
    implementation 'com.google.code.gson:gson:2.6.2'
}

使用

        CacheFactory cacheFactory = new CacheFactory(new DefaultCacheStrategy(
                new MemoryCache(),
                new LocalCache(),
                new AssetCache()
        ));
        //获取数据
        cacheFactory.getData(cacheParams);
        //缓存数据
        cacheFactory.saveData(cacheParams,dataObject);

更多用法详见demo

其他

如果你正好要做缓存,也是使用RxJava,这个方案可供参考。欢迎拍砖。

源码地址:https://github.com/pphdsny/cache/

实战来了,欢迎点击:构建高复用的搜索筛选项(实现篇)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,397评论 25 707
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生x阅读 15,967评论 3 119
  • 表单form,是让用户输入信息,浏览器搜集信息传给后端的功能区,在HTML中,表单要用 ... 标签包起来,这样浏...
    辉夜乀阅读 342评论 0 0
  • 熟悉利用函数查找字符串。 注意strcmp等算法调用的库。 定义的算法函数中尽量不要有scanf,要放在主函数ma...
    TG帅阅读 60评论 0 0
  • 今天在朋友圈发了句感言,儿子因为敬畏老师,最讨厌背英语的他,早起乖乖在桌前背英语。晚上他看到,说我用词不当,不是敬...
    开心_14c8阅读 199评论 0 0