package com.think.uiloader.data.cache.internal; import android.content.Context; import android.graphics.Bitmap; import android.os.Looper; import android.text.TextUtils; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.Serializable; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Created by borney on 3/1/17. */ public final class TCache implements CacheManager { /** * 默认硬盘缓存存储空间大小 */ public static final int DEFAULT_MAX_DISK_SPACE = 10 * 1024 * 1024; /** * 默认硬盘缓存存储空间文件最多个数 */ public static final int DEFAULT_MAX_DISK_FILE_COUNT = 100; private String cacheDir; private Cache diskCacheManager; private Cache memoryCacheManager; private final static Map<String, TCache> T_CACHE_MAP = new ConcurrentHashMap<>(); private TCache() { } public static TCache get(Context context) { return get(context, "tcache"); } public static TCache get(Context context, String relativeCacheDir) { return get(context, relativeCacheDir, DEFAULT_MAX_DISK_FILE_COUNT, DEFAULT_MAX_DISK_SPACE); } public static TCache get(Context context, String relativeCacheDir, int maxDiskTotalCount, int maxDiskTotalSpace) { return get(context, relativeCacheDir, maxDiskTotalCount, maxDiskTotalSpace, Integer.MAX_VALUE); } public static TCache get(Context context, String relativeCacheDir, int maxDiskTotalCount, int maxDiskTotalSpace, int defCacheAge) { Optional.checkNotNull(context, "context is null !!!"); checkDirArgument(relativeCacheDir, "relativeCacheDir"); String cacheDir = context.getFilesDir().getAbsolutePath() + File.separator + relativeCacheDir; return getCacheManager(cacheDir, maxDiskTotalCount, maxDiskTotalSpace, defCacheAge); } private static TCache getCacheManager(String cacheDir, int maxDiskTotalCount, int maxDiskTotalSpace, int defCacheAge) { TCache cache = getTCache(cacheDir); cache.cacheDir = cacheDir; cache.diskCacheManager = new DiskCacheManager(new FileManager(), cache.cacheDir, maxDiskTotalCount, maxDiskTotalSpace, defCacheAge); if (cache.memoryCacheManager != null) { cache.memoryCacheManager.evictAll(); } else { cache.memoryCacheManager = new MemoryCacheManager(); } return cache; } private static TCache getTCache(String cacheDir) { TCache cache = T_CACHE_MAP.get(cacheDir); if (cache == null) { cache = new TCache(); T_CACHE_MAP.put(cacheDir, cache); } return cache; } @Override public void putBytes(String key, byte[] bytes) { putByteMapper(key, bytes, new BytesMapper()); } @Override public byte[] getBytes(String key) { return getByteMapper(key, new BytesMapper()); } @Override public void putBitmap(String key, Bitmap bitmap) { putByteMapper(key, bitmap, new BitmapByteMapper()); } @Override public Bitmap getBitmap(String key) { return getByteMapper(key, new BitmapByteMapper()); } @Override public <T extends Serializable> void putSerializable(String key, T obj) { putByteMapper(key, obj, new SerializableByteMapper()); } @Override public <T extends Serializable> T getSerializable(String key) { return (T) getByteMapper(key, new SerializableByteMapper()); } @Override public void putJSONObject(String key, JSONObject obj) { putSerializable(key, obj.toString()); } @Override public JSONObject getJSONObject(String key) throws JSONException { return new JSONObject((String) getSerializable(key)); } @Override public <T> void putByteMapper(String key, T obj, ByteMapper<T> mapper) { if (Looper.myLooper() == Looper.getMainLooper()) { throw new RuntimeException("Can not operate in the main thread !!!"); } Optional.checkNotNull(obj, "obj is null !!!"); Optional.checkNotNull(mapper, "mapper is null !!!"); String k = absoluteKey(key); diskCacheManager.putByteMapper(k, obj, mapper); memoryCacheManager.putByteMapper(k, obj, mapper); } @Override public <T> T getByteMapper(String key, ByteMapper<T> mapper) { String k = absoluteKey(key); T obj = memoryCacheManager.getByteMapper(k, mapper); if (obj == null) { obj = diskCacheManager.getByteMapper(k, mapper); memoryCacheManager.putByteMapper(k, obj, mapper); } return obj; } @Override public boolean isExpired(String key) { String k = absoluteKey(key); return diskCacheManager.isExpired(k); } @Override public boolean isExpired(String key, long age) { String k = absoluteKey(key); return diskCacheManager.isExpired(k, age); } @Override public synchronized void evict(String key) { String k = absoluteKey(key); diskCacheManager.evict(k); memoryCacheManager.evict(k); } @Override public synchronized void evictAll() { diskCacheManager.evictAll(); memoryCacheManager.evictAll(); } @Override public boolean isCached(String key) { String k = absoluteKey(key); return memoryCacheManager.isCached(k) || diskCacheManager.isCached(k); } /** * recycle current cache manager and memory cache */ @SuppressWarnings("unused") public void recycle() { memoryCacheManager.evictAll(); T_CACHE_MAP.remove(cacheDir); memoryCacheManager = null; diskCacheManager = null; } /** * recycle all tcache */ @SuppressWarnings("unused") public static void recycleAll() { Iterator<TCache> iterator = T_CACHE_MAP.values().iterator(); while (iterator.hasNext()) { TCache cache = iterator.next(); cache.memoryCacheManager.evictAll(); iterator.remove(); cache.memoryCacheManager = null; cache.diskCacheManager = null; } } private String absoluteKey(String key) { checkDirArgument(key, "key"); return new StringBuilder() .append(cacheDir) .append(File.separator) .append(key) .toString(); } private static void checkDirArgument(String dir, String tag) { if (TextUtils.isEmpty(dir)) { throw new IllegalArgumentException(tag + " can not empty!!!"); } String trim = dir.trim(); if (!trim.equals(dir)) { throw new IllegalArgumentException(tag + " not start or end with blank!!"); } if (trim.startsWith(File.separator) || trim.endsWith(File.separator)) { throw new IllegalArgumentException( tag + " not start or end with " + File.separator + "!!"); } } }