Android开发经验谈Android开发Android知识

EasyCache,实现内存缓存和磁盘缓存

2017-11-04  本文已影响383人  h2coder

引言

思想

该库特点

  1. 只需要新建一个缓存类,例如UserInfoCache,继承BaseCache,重写put()方法存储数据,get()方法读取数据,removeCache()方法移除缓存。

  2. 提供一个参数类,例如UserInfoCacheParams,继承BaseCacheParams,该类在BaseCache的子类重写removeCache()、put()、get()方法中传入,作为所有参数的容器。

  3. 子类内部直接可以拿到mMemoryCache内存缓存对象,mDiskCache磁盘缓存对象,以及双缓存mOperate对象。可根据具体业务仅选用DiskCache缓存还是仅LruCache内存保存缓存,还是Operate进行内存、磁盘双缓存。

库结构

快速使用

//调用后台接口,获取用户信息
String json = requestUserInfo();
JSONObject jsonObject = new JSONObject(json);
String userId = jsonObject.optString("id");
//保存用户信息的json到缓存
UserInfoCache cache = CacheFactory.create(UserInfoCache.class);
UserInfoCacheParams params = new UserInfoCacheParams();
params.putUserId(userId);
cache.put(params, json);            
//读取缓存的json
String json = cache.get(new UserInfoCacheParams().putUserId(userId));

具体实现

/**
 * Created by Hezihao on 2017/8/4.
 * 数据缓存,提供内存缓存和磁盘缓存数据
 */
 
public class CacheOperate {
    private LruCache<String, Object> mLruCache;
    private ACache mDiskCache;
    private Context context;
    private int versionCode;
    private static boolean isInited = false;

    private CacheOperate() {
    }

    private static class SingletonHolder {
        private static final CacheOperate instance = new CacheOperate();
    }

    /**
     * 初始化,会保存Context,最好传入ApplicationContext
     *
     * @return
     */
    public static CacheOperate init(CacheConfig config) {
        if (isInited) {
            return SingletonHolder.instance;
        } else {
            CacheOperate instance = SingletonHolder.instance;
            instance.context = config.getContext();
            instance.versionCode = config.getVersionCode();
            instance.mLruCache = new LruCache<String, Object>(config.getMemoryMaxSize());
            instance.mDiskCache = ACache.get(config.getContext(), config.getCacheFileName()
                    , config.getDiskMaxSize(), config.getDiskMaxCount());
            isInited = true;
            return instance;
        }
    }

    public static CacheOperate getInstance() {
        if (!isInited) {
            throw new IllegalStateException("必须先调用init(),初始化");
        }
        return SingletonHolder.instance;
    }

    public LruCache<String, Object> getLruCache() {
        return mLruCache;
    }

    public ACache getDiskCache() {
        return mDiskCache;
    }

    public Context getContext() {
        return context;
    }

    public int getVersionCode() {
        return versionCode;
    }

    /**
     * 永久保存集合对象
     *
     * @param key
     * @param list
     * @param <T>
     */
    public <T extends Serializable> void putListData(@NonNull String key, @NonNull List<T> list) {
        putListData(key, list, -1);
    }

    public <T extends Serializable> void putListData(@NonNull String key, @NonNull List<T> list, @Nullable int saveTime) {
        ArrayList<T> dataList = new ArrayList<T>(list);
        mLruCache.put(key, list);
        mDiskCache.put(key, dataList, saveTime);
    }

    /**
     * 永久保存序列化数据
     *
     * @param key
     * @param data
     * @param <T>
     */
    public <T extends Serializable> void putData(@NonNull String key, @NonNull T data) {
        putData(key, data, -1);
    }

    public <T extends Serializable> void putData(@NonNull String key, @NonNull T data, @Nullable int saveTime) {
        mLruCache.put(key, data);
        mDiskCache.put(key, data, saveTime);
    }

    /**
     * 获取数据
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T extends Serializable> T getData(@NonNull String key) {
        return getData(key, null);
    }

    public <T extends Serializable> T getData(@NonNull String key, @Nullable T defaultValue) {
        T result = (T) mLruCache.get(key);
        if (result == null) {
            result = (T) mDiskCache.getAsObject(key);
            if (result == null && defaultValue != null) {
                result = defaultValue;
            }
            if (result != null) {
                mLruCache.put(key, result);
            } else {
                return defaultValue;
            }
        }
        return result;
    }

    /**
     * 按key在内存缓存中移除
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T extends Serializable> T removeMemoryCache(@NonNull String key) {
        return (T) mLruCache.remove(key);
    }

    /**
     * 移除磁盘缓存
     *
     * @param key
     * @return
     */
    public <T extends Serializable> T removeDiskCache(@NonNull String key) {
        Object cache = mDiskCache.getAsObject(key);
        if (cache != null) {
            mDiskCache.remove(key);
            return (T) cache;
        } else {
            return null;
        }
    }

    /**
     * 移除内存缓存和磁盘缓存
     */
    public void removeCache(@NonNull String key) {
        removeMemoryCache(key);
        removeDiskCache(key);
    }

    /**
     * 移除所有Lru内存缓存
     */
    public void removeAllMemoryCache() {
        mLruCache.evictAll();
    }

    /**
     * 移除所有Disk磁盘缓存
     */
    public void removeAllDiskCache() {
        mDiskCache.clear();
    }
}
public interface ICache {
    /**
     * 获取操作对象
     *
     * @return
     */
    CacheOperate getOperate();

    /**
     * 获取VersionCode,通常为App的VersionCode
     *
     * @return
     */
    int getVersionCode();

    /**
     * 获取Version标志,通常为特定字符拼接VersionCode
     *
     * @return
     */
    String getVersionSymbol();
}
/**
 * Created by Hezihao on 2017/8/4.
 */

public abstract class BaseCache<P extends BaseCacheParams> implements ICache {
    private String versionSymbol;

    public CacheOperate getOperate() {
        return CacheOperate.getInstance();
    }

    @Override
    public int getVersionCode() {
        return getOperate().getVersionCode();
    }

    @Override
    public String getVersionSymbol() {
        if (versionSymbol != null) {
            return versionSymbol;
        } else {
            new StringBuilder()
                    .append("v")
                    .append(getVersionCode())
                    .append("_");
            return versionSymbol;
        }
    }

    public abstract void removeCache(@Nullable P params);

    public abstract void put(@Nullable P params, Serializable target);

    public abstract <T extends Serializable> T get(@Nullable P params);
}
/**
 * Created by Hezihao on 2017/9/8.
 * 参数类Map
 */

public interface ICacheParams {
    /**
     * 获取VersionCode,通常为App的VersionCode
     *
     * @return
     */
    int getVersionCode();

    /**
     * 获取Version标志,通常为特定字符拼接VersionCode
     *
     * @return
     */
    String getVersionSymbol();

    /**
     * 将参数存进容器,子类定义容器,通常为Map
     *
     * @param key    键
     * @param target 要存入的数据
     * @param <P>
     * @return
     */
    <P extends ICacheParams> P put(String key, Serializable target);

    /**
     * 从容器中取出参数
     *
     * @param key 键
     * @param <T>
     * @return
     */
    <T extends Serializable> T get(String key);

    /**
     * 从容器中取出参数,可设置默认值
     *
     * @param key          键
     * @param defaultValue 默认值
     * @param <T>
     * @return
     */
    <T extends Serializable> T get(String key, Serializable defaultValue);
}
/**
 * Created by Hezihao on 2017/9/8.
 * Cache使用时,可附带参数
 */

public abstract class BaseCacheParams implements ICacheParams {
    private HashMap<String, Serializable> paramsMap;
    private String versionSymbol;

    @Override
    public int getVersionCode() {
        return CacheOperate.getInstance().getVersionCode();
    }

    @Override
    public String getVersionSymbol() {
        if (versionSymbol != null) {
            return versionSymbol;
        } else {
            new StringBuilder()
                    .append("v")
                    .append(getVersionCode())
                    .append("_");
            return versionSymbol;
        }
    }

    private HashMap<String, Serializable> getParamsMap() {
        if (paramsMap == null) {
            paramsMap = new HashMap<String, Serializable>();
        }
        return paramsMap;
    }

    @Override
    public <P extends ICacheParams> P put(String key, Serializable target) {
        getParamsMap().put(key, target);
        return (P) this;
    }

    @Override
    public <T extends Serializable> T get(String key) {
        return get(key, null);
    }

    @Override
    public <T extends Serializable> T get(String key, Serializable defaultValue) {
        T value = (T) getParamsMap().get(key);
        if (value == null) {
            return (T) defaultValue;
        } else {
            return value;
        }
    }
}
public class CacheFactory {
    /**
     * 缓存Map,缓存ICache的实例,以子类的Class作为Key,ICache实例作为Value
     */
    private static final ConcurrentHashMap<Class<?>, ICache> mCacheMap = new ConcurrentHashMap<Class<?>, ICache>();

    private CacheFactory() {
    }

    /**
     * 反射构造BaseCache子类,并存入到缓存Map中,如果在缓存中有,则直接返回缓存中缓存实例
     *
     * @param clazz 要构造的BaseCache的Class
     * @param <T>   泛型,限制为ICache的实现类
     * @return 返回要构造的BaseCache的子类
     */
    public static <T extends ICache> T create(Class<T> clazz) {
        ICache cache = mCacheMap.get(clazz);
        if (cache == null) {
            Constructor<T> constructor = null;
            try {
                constructor = clazz.getDeclaredConstructor();
                constructor.setAccessible(true);
                cache = constructor.newInstance();
                mCacheMap.put(clazz, cache);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return (T) cache;
    }

    /**
     * 从缓存中移除缓存实例
     *
     * @param clazz 缓存的子类Class
     * @param <T>   泛型,限制ICache的子类
     * @return 返回移除前缓存的实例
     */
    public static <T extends ICache> T removeCache(Class<T> clazz) {
        ICache cache = mCacheMap.get(clazz);
        if (cache != null) {
            mCacheMap.remove(clazz);
            return (T) cache;
        } else {
            return null;
        }
    }

    public static void removeAllCache() {
        mCacheMap.clear();
    }
}
public class CacheConfig {
    private static final int M = 1024 * 1024;
    //默认磁盘缓存保存文件的文件名
    private static final String DEFAULT_CACHE_FILE_NAME = "ACache";
    //默认磁盘缓存存储大小,默认50 MB
    private static final int DEFAULT_DISK_CACHE_MAX_SIZE = 1000 * 1000 * 50;
    //默认磁盘缓存存储数量,默认不限制
    private static final int DEFAULT_DISK_CACHE_MAX_COUNT = Integer.MAX_VALUE;
    //默认内存缓存数量
    private static final int DEFAULT_MEMORY_CACHE_SIZE = 5 * M;

    private Context context;
    private int versionCode = 0;
    private String cacheFileName;
    private long diskMaxSize;
    private int diskMaxCount;
    private int memoryMaxSize;

    public CacheConfig(Builder builder) {
        this.context = builder.getContext();
        this.versionCode = builder.getVersionCode();
        this.cacheFileName = builder.getCacheFileName();
        this.diskMaxSize = builder.getDiskMaxSize();
        this.diskMaxCount = builder.getDiskMaxCount();
        this.memoryMaxSize = builder.getMemoryMaxSize();
    }

    public static Builder newBuilder(Context context, int versionCode) {
        return new Builder(context, versionCode);
    }

    public Context getContext() {
        return context;
    }

    public int getVersionCode() {
        return versionCode;
    }

    public String getCacheFileName() {
        return cacheFileName;
    }

    public long getDiskMaxSize() {
        return diskMaxSize;
    }

    public int getDiskMaxCount() {
        return diskMaxCount;
    }

    public int getMemoryMaxSize() {
        return memoryMaxSize;
    }

    public static class Builder {
        private Context context;
        private int versionCode;
        private String cacheFileName = DEFAULT_CACHE_FILE_NAME;
        private long diskMaxSize = DEFAULT_DISK_CACHE_MAX_SIZE;
        private int diskMaxCount = DEFAULT_DISK_CACHE_MAX_COUNT;
        private int memoryMaxSize = DEFAULT_MEMORY_CACHE_SIZE;

        private Builder(Context context, int versionCode) {
            this.context = context;
            this.versionCode = versionCode;
        }

        public Builder withCacheFileName(String cacheFileName) {
            this.cacheFileName = cacheFileName;
            return this;
        }

        public Builder withDiskMaxSize(long maxSize) {
            this.diskMaxSize = maxSize;
            return this;
        }

        public Builder withDiskMaxCount(int maxCount) {
            this.diskMaxCount = maxCount;
            return this;
        }

        public Builder withMemoryMaxSize(int memoryMaxSize) {
            this.memoryMaxSize = memoryMaxSize;
            return this;
        }

        public Context getContext() {
            return context;
        }

        public int getVersionCode() {
            return versionCode;
        }

        public String getCacheFileName() {
            return cacheFileName;
        }

        public long getDiskMaxSize() {
            return diskMaxSize;
        }

        public int getDiskMaxCount() {
            return diskMaxCount;
        }

        public int getMemoryMaxSize() {
            return memoryMaxSize;
        }

        public CacheConfig build() {
            return new CacheConfig(this);
        }
    }
}
public class CacheManager {
    private CacheManager() {
    }

    private static final class SingletonHolder {
        private static final CacheManager instance = new CacheManager();
    }

    public static CacheManager getInstance() {
        return SingletonHolder.instance;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        if (context == null) {
            throw new NullPointerException("context 不能为空");
        }
        int versionCode = 0;
        try {
            versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        CacheOperate.init(CacheConfig.newBuilder(context, versionCode).build());
    }

    /**
     * 移除所有内存中的缓存实例
     */
    public void removeAllCache() {
        CacheFactory.removeAllCache();
    }
}

结语

上一篇 下一篇

猜你喜欢

热点阅读