Browse Source

二级缓存之磁盘缓存优化

杨充 4 years ago
parent
commit
6171009db0
31 changed files with 701 additions and 877 deletions
  1. 1 2
      VideoSqlLite/src/main/java/com/yc/videosqllite/cache/InterCache.java
  2. 0 1
      VideoSqlLite/src/main/java/com/yc/videosqllite/cache/VideoLruCache.java
  3. 19 17
      VideoSqlLite/src/main/java/com/yc/videosqllite/cache/VideoMapCache.java
  4. 102 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskCacheWriteLocker.java
  5. 19 3
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskFileUtils.java
  6. 35 7
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCache.java
  7. 62 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCacheFactory.java
  8. 184 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCacheWrapper.java
  9. 18 1
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskUtils.java
  10. 67 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/ExternalDiskCacheFactory.java
  11. 24 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InterDiskCache.java
  12. 11 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InterDiskFactory.java
  13. 43 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InternalDiskCacheFactory.java
  14. 23 111
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/SqlLiteCache.java
  15. 1 1
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/Synthetic.java
  16. 0 73
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCache.java
  17. 0 29
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheAdapter.java
  18. 0 97
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheWriteLocker.java
  19. 0 72
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheFactory.java
  20. 0 182
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheWrapper.java
  21. 0 38
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalCacheDiskCacheFactory.java
  22. 0 67
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalPreferredCacheDiskCacheFactory.java
  23. 0 40
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/InternalCacheDiskCacheFactory.java
  24. 0 42
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Key.java
  25. 0 54
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Preconditions.java
  26. 0 23
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/SafeKeyGenerator.java
  27. 3 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/manager/CacheConfig.java
  28. 36 13
      VideoSqlLite/src/main/java/com/yc/videosqllite/manager/LocationManager.java
  29. 49 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/model/SafeKeyGenerator.java
  30. 3 3
      VideoSqlLite/src/main/java/com/yc/videosqllite/model/VideoLocation.java
  31. 1 1
      VideoSqlLite/src/main/java/com/yc/videosqllite/utils/CacheLogUtils.java

+ 1 - 2
VideoSqlLite/src/main/java/com/yc/videosqllite/cache/InterCache.java

@@ -3,14 +3,13 @@ package com.yc.videosqllite.cache;
 import java.util.Set;
 
 
-
 /**
  * <pre>
  *     @author yangchong
  *     email  : yangchong211@163.com
  *     time  : 2020/8/6
  *     desc  : 缓存接口
- *     revise:
+ *     revise: 内存缓存,主要使用到了淘汰算法
  * </pre>
  */
 public interface InterCache<K, V> {

+ 0 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/cache/VideoLruCache.java

@@ -5,7 +5,6 @@ import java.util.Map;
 import java.util.Set;
 
 
-
 /**
  * <pre>
  *     @author yangchong

+ 19 - 17
VideoSqlLite/src/main/java/com/yc/videosqllite/cache/VideoMapCache.java

@@ -1,8 +1,7 @@
 package com.yc.videosqllite.cache;
 
-import com.yc.videosqllite.manager.CacheConfig;
+import com.yc.videosqllite.model.SafeKeyGenerator;
 import com.yc.videosqllite.model.VideoLocation;
-import com.yc.videosqllite.utils.VideoMd5Utils;
 
 /**
  * <pre>
@@ -15,16 +14,16 @@ import com.yc.videosqllite.utils.VideoMd5Utils;
  */
 public class VideoMapCache {
 
-    private CacheConfig cacheConfig;
     /**
      * 缓存
      */
     private InterCache<String, VideoLocation> mCache;
+    private final SafeKeyGenerator safeKeyGenerator;
 
-    public VideoMapCache(CacheConfig cacheConfig){
-        this.cacheConfig = cacheConfig;
+    public VideoMapCache(){
         //默认设置存储最大值为1000条
         mCache =  new VideoLruCache<>(1000);
+        this.safeKeyGenerator = new SafeKeyGenerator();
     }
 
     /**
@@ -39,9 +38,10 @@ public class VideoMapCache {
         if (location==null){
             return;
         }
-        String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-        location.setUrlMd5(key);
-        mCache.put(key,location);
+        //String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        String safeKey = safeKeyGenerator.getSafeKey(url);
+        location.setUrlMd5(safeKey);
+        mCache.put(safeKey,location);
     }
 
     /**
@@ -51,21 +51,22 @@ public class VideoMapCache {
      */
     public synchronized long get(String url){
         if (url==null || url.length()==0){
-            return 0;
+            return -1;
         }
-        String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        //String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        String key = safeKeyGenerator.getSafeKey(url);
         VideoLocation videoLocation = mCache.get(key);
         if (videoLocation==null){
             //没找到
-            return 0;
+            return -1;
         }
         if (videoLocation.getTotalTime()<=videoLocation.getPosition()){
             //这一步主要是避免外部开发员瞎存播放进度
-            return 0;
+            return -1;
         }
         long position = videoLocation.getPosition();
         if (position<0){
-            position = 0;
+            position = -1;
         }
         return position;
     }
@@ -79,7 +80,8 @@ public class VideoMapCache {
         if (url==null || url.length()==0){
             return false;
         }
-        String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        //String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        String key = safeKeyGenerator.getSafeKey(url);
         VideoLocation location = mCache.remove(key);
         if (location==null){
             return false;
@@ -98,9 +100,9 @@ public class VideoMapCache {
         if (url==null || url.length()==0){
             return false;
         }
-        String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-        boolean containsKey = mCache.containsKey(key);
-        return containsKey;
+        //String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+        String key = safeKeyGenerator.getSafeKey(url);
+        return mCache.containsKey(key);
     }
 
 

+ 102 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskCacheWriteLocker.java

@@ -0,0 +1,102 @@
+package com.yc.videosqllite.disk;
+
+
+
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存写,自定义锁
+ *     revise:
+ * </pre>
+ */
+public final class DiskCacheWriteLocker {
+
+    private final Map<String, WriteLock> locks = new HashMap<>();
+    private final WriteLockPool writeLockPool = new WriteLockPool();
+
+    void acquire(String safeKey) {
+        WriteLock writeLock;
+        synchronized (this) {
+            writeLock = locks.get(safeKey);
+            if (writeLock == null) {
+                writeLock = writeLockPool.obtain();
+                locks.put(safeKey, writeLock);
+            }
+            writeLock.interestedThreads++;
+        }
+        writeLock.lock.lock();
+    }
+
+    void release(String safeKey) {
+        WriteLock writeLock;
+        synchronized (this) {
+            writeLock = DiskUtils.checkNotNull(locks.get(safeKey));
+            if (writeLock.interestedThreads < 1) {
+                throw new IllegalStateException("Cannot release a lock that is not held"
+                        + ", safeKey: " + safeKey
+                        + ", interestedThreads: " + writeLock.interestedThreads);
+            }
+            writeLock.interestedThreads--;
+            if (writeLock.interestedThreads == 0) {
+                WriteLock removed = locks.remove(safeKey);
+                if (removed != null && !removed.equals(writeLock)) {
+                    throw new IllegalStateException("Removed the wrong lock"
+                            + ", expected to remove: " + writeLock
+                            + ", but actually removed: " + removed
+                            + ", safeKey: " + safeKey);
+                }
+                writeLockPool.offer(removed);
+            }
+        }
+
+        writeLock.lock.unlock();
+    }
+
+    private static class WriteLock {
+        final Lock lock = new ReentrantLock();
+        int interestedThreads;
+
+        @Synthetic
+        WriteLock() {
+        }
+    }
+
+    private static class WriteLockPool {
+        private static final int MAX_POOL_SIZE = 10;
+        private final Queue<WriteLock> pool = new ArrayDeque<>();
+
+        @Synthetic
+        WriteLockPool() {
+        }
+
+        WriteLock obtain() {
+            WriteLock result;
+            synchronized (pool) {
+                result = pool.poll();
+            }
+            if (result == null) {
+                result = new WriteLock();
+            }
+            return result;
+        }
+
+        void offer(WriteLock writeLock) {
+            synchronized (pool) {
+                if (pool.size() < MAX_POOL_SIZE) {
+                    pool.offer(writeLock);
+                }
+            }
+        }
+    }
+
+
+}

+ 19 - 3
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskFileUtils.java

@@ -25,7 +25,7 @@ import java.util.List;
  *     revise:
  * </pre>
  */
-public class DiskFileUtils {
+public final class DiskFileUtils {
 
     /**
      * 目录地址
@@ -37,11 +37,24 @@ public class DiskFileUtils {
         return path;
     }
 
+    /**
+     * 目录地址
+     * SDCard/Android/data/<application package>/cache
+     * data/data/<application package>/cache
+     * @param context                               上下文
+     * @param pathName                              路径名称
+     * @return
+     */
     public static String getPath(Context context , String pathName) {
         String path = getCachePath(context) + File.separator + pathName;
         return path;
     }
 
+    /**
+     * 获取路径file
+     * @param context                               上下文
+     * @return
+     */
     public static File getFilePath(Context context){
         String path = getPath(context);
         File file = new File(path);
@@ -50,10 +63,13 @@ public class DiskFileUtils {
 
     /**
      * 获取app缓存路径
+     * 如果sd卡可以使用,sd卡路径
      * SDCard/Android/data/<application package>/cache
+     *
+     * 如果没有sd卡,则获取内部存储卡路径
      * data/data/<application package>/cache
      *
-     * @param context
+     * @param context                               上下文
      * @return
      */
     public static String getCachePath(Context context) {
@@ -79,7 +95,7 @@ public class DiskFileUtils {
      * @return
      */
     public static List<File> getFileList(Context context) {
-        File file = new File(DiskFileUtils.getPath(context));
+        File file = new File(com.yc.videosqllite.disk.DiskFileUtils.getPath(context));
         List<File> mFileList = new ArrayList<>();
         File[] fileArray = file.listFiles();
         if (fileArray == null || fileArray.length <= 0) {

+ 35 - 7
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCache.java

@@ -34,6 +34,34 @@ import java.util.concurrent.TimeUnit;
  */
 public final class DiskLruCache implements Closeable {
 
+
+    /**
+     * libcore.io.DiskLruCache
+     * 1
+     * 1
+     * 1
+     *
+     * DIRTY 27c7e00adbacc71dc793e5e7bf02f861
+     * CLEAN 27c7e00adbacc71dc793e5e7bf02f861 1208
+     * READ 27c7e00adbacc71dc793e5e7bf02f861
+     * DIRTY b80f9eec4b616dc6682c7fa8bas2061f
+     * CLEAN b80f9eec4b616dc6682c7fa8bas2061f 1208
+     * READ b80f9eec4b616dc6682c7fa8bas2061f
+     * DIRTY be3fgac81c12a08e89088555d85dfd2b
+     * CLEAN be3fgac81c12a08e89088555d85dfd2b 99
+     * READ be3fgac81c12a08e89088555d85dfd2b
+     * DIRTY 536990f4dbddfghcfbb8f350a941wsxd
+     * REMOVE 536990f4dbddfghcfbb8f350a941wsxd
+     *
+     * 第1行:libcore.io.DiskLruCache 是固定字符串,表明使用的是 DiskLruCache 技术;
+     * 第2行:DiskLruCache 的版本号,源码中为常量 1;
+     * 第3行:APP 的版本号,即我们在 open() 方法里传入的版本号;
+     * 第4行:valueCount,这个值也是在 open() 方法中传入的,指每个 key 对应几个文件,通常情况下都为 1;
+     * 第5行:空行
+     *
+     *
+     */
+
     static final String JOURNAL_FILE = "journal";
     static final String JOURNAL_FILE_TEMP = "journal.tmp";
     static final String JOURNAL_FILE_BACKUP = "journal.bkp";
@@ -73,7 +101,7 @@ public final class DiskLruCache implements Closeable {
                     new DiskLruCacheThreadFactory());
     private final Callable<Void> cleanupCallable = new Callable<Void>() {
         public Void call() throws Exception {
-            synchronized (DiskLruCache.this) {
+            synchronized (com.yc.videosqllite.disk.DiskLruCache.this) {
                 if (journalWriter == null) {
                     return null; // Closed.
                 }
@@ -110,7 +138,7 @@ public final class DiskLruCache implements Closeable {
      * @param maxSize    the maximum number of bytes this cache should use to store
      * @throws IOException if reading or writing the cache directory fails
      */
-    public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
+    public static com.yc.videosqllite.disk.DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
             throws IOException {
         if (maxSize <= 0) {
             throw new IllegalArgumentException("maxSize <= 0");
@@ -132,7 +160,7 @@ public final class DiskLruCache implements Closeable {
         }
 
         // Prefer to pick up where we left off.
-        DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
+        com.yc.videosqllite.disk.DiskLruCache cache = new com.yc.videosqllite.disk.DiskLruCache(directory, appVersion, valueCount, maxSize);
         if (cache.journalFile.exists()) {
             try {
                 cache.readJournal();
@@ -151,7 +179,7 @@ public final class DiskLruCache implements Closeable {
 
         // Create a new empty cache.
         directory.mkdirs();
-        cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
+        cache = new com.yc.videosqllite.disk.DiskLruCache(directory, appVersion, valueCount, maxSize);
         cache.rebuildJournal();
         return cache;
     }
@@ -610,7 +638,7 @@ public final class DiskLruCache implements Closeable {
          * is in progress.
          */
         public Editor edit() throws IOException {
-            return DiskLruCache.this.edit(key, sequenceNumber);
+            return com.yc.videosqllite.disk.DiskLruCache.this.edit(key, sequenceNumber);
         }
 
         public File getFile(int index) {
@@ -651,7 +679,7 @@ public final class DiskLruCache implements Closeable {
          * or null if no value has been committed.
          */
         private InputStream newInputStream(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
+            synchronized (com.yc.videosqllite.disk.DiskLruCache.this) {
                 if (entry.currentEditor != this) {
                     throw new IllegalStateException();
                 }
@@ -676,7 +704,7 @@ public final class DiskLruCache implements Closeable {
         }
 
         public File getFile(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
+            synchronized (com.yc.videosqllite.disk.DiskLruCache.this) {
                 if (entry.currentEditor != this) {
                     throw new IllegalStateException();
                 }

+ 62 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCacheFactory.java

@@ -0,0 +1,62 @@
+package com.yc.videosqllite.disk;
+
+import com.yc.videosqllite.model.SafeKeyGenerator;
+
+import java.io.File;
+
+public class DiskLruCacheFactory implements InterDiskFactory {
+
+    private final long diskCacheSize;
+    private final DiskLruCacheFactory.CacheDirectoryGetter cacheDirectoryGetter;
+
+    /**
+     * 接口被UI线程调用以获取缓存文件夹。
+     */
+    public interface CacheDirectoryGetter {
+        File getCacheDirectory();
+    }
+
+    public DiskLruCacheFactory(final String diskCacheFolder, long diskCacheSize) {
+        this(new DiskLruCacheFactory.CacheDirectoryGetter() {
+            @Override
+            public File getCacheDirectory() {
+                return new File(diskCacheFolder);
+            }
+        }, diskCacheSize);
+    }
+
+    public DiskLruCacheFactory(final String diskCacheFolder, final String diskCacheName, long diskCacheSize) {
+        this(new DiskLruCacheFactory.CacheDirectoryGetter() {
+            @Override
+            public File getCacheDirectory() {
+                return new File(diskCacheFolder, diskCacheName);
+            }
+        }, diskCacheSize);
+    }
+
+    /**
+     * When using this constructor {@link DiskLruCacheFactory.CacheDirectoryGetter#getCacheDirectory()} will be called out
+     * of UI thread, allowing to do I/O access without performance impacts.
+     *
+     * @param cacheDirectoryGetter                          接口被UI线程调用以获取缓存文件夹
+     * @param diskCacheSize                                 LRU磁盘缓存所需的最大字节大小
+     */
+    @SuppressWarnings("WeakerAccess")
+    public DiskLruCacheFactory(DiskLruCacheFactory.CacheDirectoryGetter cacheDirectoryGetter, long diskCacheSize) {
+        this.diskCacheSize = diskCacheSize;
+        this.cacheDirectoryGetter = cacheDirectoryGetter;
+    }
+
+    @Override
+    public InterDiskCache build() {
+        File cacheDir = cacheDirectoryGetter.getCacheDirectory();
+        if (cacheDir == null) {
+            return null;
+        }
+        if (!cacheDir.mkdirs() && (!cacheDir.exists() || !cacheDir.isDirectory())) {
+            return null;
+        }
+        return DiskLruCacheWrapper.create(cacheDir, new SafeKeyGenerator());
+    }
+}
+

+ 184 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCacheWrapper.java

@@ -0,0 +1,184 @@
+package com.yc.videosqllite.disk;
+
+
+import androidx.annotation.Nullable;
+
+import com.yc.videosqllite.manager.CacheConfig;
+import com.yc.videosqllite.manager.LocationManager;
+import com.yc.videosqllite.model.SafeKeyGenerator;
+import com.yc.videosqllite.utils.CacheLogUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存实现类
+ *     revise:
+ * </pre>
+ */
+public class DiskLruCacheWrapper implements InterDiskCache {
+
+    private static final int APP_VERSION = 1;
+    private static final int VALUE_COUNT = 1;
+    private static DiskLruCacheWrapper wrapper;
+    public final SafeKeyGenerator safeKeyGenerator;
+    private final File directory;
+    private final long maxSize;
+    private final DiskCacheWriteLocker writeLocker = new DiskCacheWriteLocker();
+    private DiskLruCache diskLruCache;
+
+    @SuppressWarnings("deprecation")
+    public static synchronized InterDiskCache get(File directory, SafeKeyGenerator safeKeyGenerator) {
+        if (wrapper == null) {
+            wrapper = new DiskLruCacheWrapper(directory,safeKeyGenerator);
+        }
+        return wrapper;
+    }
+
+    @SuppressWarnings("deprecation")
+    public static InterDiskCache create(File directory, SafeKeyGenerator safeKeyGenerator) {
+        return new DiskLruCacheWrapper(directory,safeKeyGenerator);
+    }
+
+    @Deprecated
+    @SuppressWarnings({"WeakerAccess", "DeprecatedIsStillUsed"})
+    protected DiskLruCacheWrapper(File directory,SafeKeyGenerator safeKeyGenerator) {
+        CacheConfig cacheConfig = LocationManager.getInstance().getCacheConfig();
+        this.directory = directory;
+        this.safeKeyGenerator = safeKeyGenerator;
+        this.maxSize = cacheConfig.getCacheMax();
+    }
+
+    private synchronized DiskLruCache getDiskCache() throws IOException {
+        if (diskLruCache == null) {
+            diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
+        }
+        return diskLruCache;
+    }
+
+    @Nullable
+    @Override
+    public String get(String key) {
+        String safeKey = safeKeyGenerator.getSafeKey(key);
+        String result = null;
+        try {
+            final DiskLruCache.Value value = getDiskCache().get(safeKey);
+            if (value != null) {
+                result = value.getString(0);
+            }
+        } catch (IOException e) {
+            CacheLogUtils.d("DiskLruCacheWrapper-----Unable to get from disk cache-"+e);
+        } finally {
+            try {
+                getDiskCache().flush();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void put(String key, String data) {
+        String safeKey = safeKeyGenerator.getSafeKey(key);
+        writeLocker.acquire(safeKey);
+        try {
+            CacheLogUtils.d("DiskLruCacheWrapper-----Put: Obtained:"+ safeKey + " for for Key: " + key);
+            try {
+                DiskLruCache diskCache = getDiskCache();
+                DiskLruCache.Value current = diskCache.get(safeKey);
+                if (current != null) {
+                    return;
+                }
+                DiskLruCache.Editor editor = diskCache.edit(safeKey);
+                if (editor == null) {
+                    throw new IllegalStateException("Had two simultaneous puts for: " + safeKey);
+                }
+                try {
+                    editor.set(0,data);
+                    editor.commit();
+                } finally {
+                    editor.abortUnlessCommitted();
+                }
+            } catch (IOException e) {
+                CacheLogUtils.d("DiskLruCacheWrapper-----Unable to put from disk cache-"+e);
+            } finally {
+                try {
+                    getDiskCache().flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        } finally {
+            writeLocker.release(safeKey);
+        }
+    }
+
+    @Override
+    public boolean remove(String key) {
+        String safeKey = safeKeyGenerator.getSafeKey(key);
+        boolean isRemove;
+        try {
+            isRemove = getDiskCache().remove(safeKey);
+        } catch (IOException e) {
+            CacheLogUtils.d("DiskLruCacheWrapper-----Unable to delete from disk cache-"+e);
+            isRemove = false;
+        } finally {
+            try {
+                getDiskCache().flush();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return isRemove;
+    }
+
+    @Override
+    public boolean containsKey(String key) {
+        String safeKey = safeKeyGenerator.getSafeKey(key);
+        boolean result = false;
+        try {
+            final DiskLruCache.Value value = getDiskCache().get(safeKey);
+            if (value != null) {
+                String string = value.getString(0);
+                if (string!=null && string.length() > 0){
+                    result = true;
+                }
+            }
+        } catch (IOException e) {
+            CacheLogUtils.d("DiskLruCacheWrapper-----Unable to get from disk cache-"+e);
+        } finally {
+            try {
+                getDiskCache().flush();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void clear() {
+        try {
+            getDiskCache().delete();
+        } catch (IOException e) {
+            CacheLogUtils.d("DiskLruCacheWrapper-----Unable to clear disk cache or disk cache cleared externally-"+e);
+        } finally {
+            try {
+                getDiskCache().flush();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            resetDiskCache();
+        }
+    }
+
+    private synchronized void resetDiskCache() {
+        diskLruCache = null;
+    }
+
+}

+ 18 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskUtils.java

@@ -1,5 +1,8 @@
 package com.yc.videosqllite.disk;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
@@ -17,7 +20,8 @@ import java.nio.charset.Charset;
  *     revise:
  * </pre>
  */
-final class DiskUtils {
+public final class DiskUtils {
+
     static final Charset US_ASCII = Charset.forName("US-ASCII");
     static final Charset UTF_8 = Charset.forName("UTF-8");
 
@@ -67,4 +71,17 @@ final class DiskUtils {
             }
         }
     }
+
+    @NonNull
+    public static <T> T checkNotNull(@Nullable T arg) {
+        return checkNotNull(arg, "Argument must not be null");
+    }
+
+    @NonNull
+    public static <T> T checkNotNull(@Nullable T arg, @NonNull String message) {
+        if (arg == null) {
+            throw new NullPointerException(message);
+        }
+        return arg;
+    }
 }

+ 67 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/ExternalDiskCacheFactory.java

@@ -0,0 +1,67 @@
+package com.yc.videosqllite.disk;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import java.io.File;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 创建一个基于外部的磁盘缓存目录,如果没有外部存储,则返回到内部磁盘缓存可用。
+ *             如果曾经退回到内部磁盘缓存,将从那一刻起使用那个缓存。
+ *     revise:
+ * </pre>
+ */
+public final class ExternalDiskCacheFactory extends DiskLruCacheFactory {
+
+    public ExternalDiskCacheFactory(Context context) {
+        this(context, InterDiskFactory.DEFAULT_DISK_CACHE_DIR, InterDiskFactory.DEFAULT_DISK_CACHE_SIZE);
+    }
+
+    public ExternalDiskCacheFactory(Context context, long diskCacheSize) {
+        this(context, InterDiskFactory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
+    }
+
+    public ExternalDiskCacheFactory(final Context context, final String diskCacheName, final long diskCacheSize) {
+        super(new CacheDirectoryGetter() {
+            @Nullable
+            private File getInternalCacheDirectory() {
+                File cacheDirectory = context.getCacheDir();
+                if (cacheDirectory == null) {
+                    return null;
+                }
+                if (diskCacheName != null) {
+                    return new File(cacheDirectory, diskCacheName);
+                }
+                return cacheDirectory;
+            }
+
+            @Override
+            public File getCacheDirectory() {
+                File internalCacheDirectory = getInternalCacheDirectory();
+
+                // Already used internal cache, so keep using that one,
+                // thus avoiding using both external and internal with transient errors.
+                if ((null != internalCacheDirectory) && internalCacheDirectory.exists()) {
+                    return internalCacheDirectory;
+                }
+
+                File cacheDirectory = context.getExternalCacheDir();
+
+                // Shared storage is not available.
+                if ((cacheDirectory == null) || (!cacheDirectory.canWrite())) {
+                    return internalCacheDirectory;
+                }
+                if (diskCacheName != null) {
+                    return new File(cacheDirectory, diskCacheName);
+                }
+                return cacheDirectory;
+            }
+        }, diskCacheSize);
+    }
+}
+

+ 24 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InterDiskCache.java

@@ -0,0 +1,24 @@
+package com.yc.videosqllite.disk;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存接口
+ *     revise:
+ * </pre>
+ */
+public interface InterDiskCache {
+
+    String get(String key);
+
+    void put(String key, String data);
+
+    boolean remove(String key);
+
+    boolean containsKey(String key);
+
+    void clear();
+
+}

+ 11 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InterDiskFactory.java

@@ -0,0 +1,11 @@
+package com.yc.videosqllite.disk;
+
+
+interface InterDiskFactory {
+
+    /** 250 MB of cache. */
+    int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;
+    String DEFAULT_DISK_CACHE_DIR = "disk";
+
+    InterDiskCache build();
+}

+ 43 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/InternalDiskCacheFactory.java

@@ -0,0 +1,43 @@
+package com.yc.videosqllite.disk;
+
+import android.content.Context;
+
+import java.io.File;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 创建一个基于内部的磁盘缓存磁盘缓存目录
+ *     revise:
+ * </pre>
+ */
+public final class InternalDiskCacheFactory extends DiskLruCacheFactory {
+
+    public InternalDiskCacheFactory(Context context) {
+        this(context, InterDiskFactory.DEFAULT_DISK_CACHE_DIR,
+                InterDiskFactory.DEFAULT_DISK_CACHE_SIZE);
+    }
+
+    public InternalDiskCacheFactory(Context context, long diskCacheSize) {
+        this(context, InterDiskFactory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
+    }
+
+    public InternalDiskCacheFactory(final Context context, final String diskCacheName,
+                                    long diskCacheSize) {
+        super(new CacheDirectoryGetter() {
+            @Override
+            public File getCacheDirectory() {
+                File cacheDirectory = context.getCacheDir();
+                if (cacheDirectory == null) {
+                    return null;
+                }
+                if (diskCacheName != null) {
+                    return new File(cacheDirectory, diskCacheName);
+                }
+                return cacheDirectory;
+            }
+        }, diskCacheSize);
+    }
+}

+ 23 - 111
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/SqlLiteCache.java

@@ -1,12 +1,12 @@
 package com.yc.videosqllite.disk;
 
 import com.yc.videosqllite.manager.CacheConfig;
+import com.yc.videosqllite.manager.LocationManager;
+import com.yc.videosqllite.model.SafeKeyGenerator;
 import com.yc.videosqllite.model.VideoLocation;
 import com.yc.videosqllite.utils.CacheLogUtils;
-import com.yc.videosqllite.utils.VideoMd5Utils;
 
 import java.io.File;
-import java.io.IOException;
 
 /**
  * <pre>
@@ -19,19 +19,16 @@ import java.io.IOException;
  */
 public class SqlLiteCache {
 
-    private CacheConfig cacheConfig;
-    private DiskLruCache diskLruCache;
+    private InterDiskCache interDiskCache;
+    public final SafeKeyGenerator safeKeyGenerator;
 
-    public SqlLiteCache(CacheConfig cacheConfig) {
-        this.cacheConfig = cacheConfig;
+    public SqlLiteCache() {
+        CacheConfig cacheConfig = LocationManager.getInstance().getCacheConfig();
         File path = DiskFileUtils.getFilePath(cacheConfig.getContext());
         String pathString = path.getPath();
-        CacheLogUtils.d("SqlLiteCache-----pathString-"+pathString);
-        try {
-            diskLruCache = DiskLruCache.open(path,1,1,cacheConfig.getCacheMax());
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        CacheLogUtils.d("SqlLiteCache-----pathString路径输出地址-"+pathString);
+        this.safeKeyGenerator = new SafeKeyGenerator();
+        interDiskCache = DiskLruCacheWrapper.get(path,safeKeyGenerator);
     }
 
     /**
@@ -40,34 +37,14 @@ public class SqlLiteCache {
      * @param location                      视频数据
      */
     public synchronized void put(String url , VideoLocation location){
-        if (url==null || url.length()==0){
-            return;
-        }
         if (location==null){
             return;
         }
-
-        if (diskLruCache!=null){
-            try {
-                String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-                CacheLogUtils.d("SqlLiteCache-----put--key--"+key);
-                DiskLruCache.Editor editor = diskLruCache.edit(key);
-                if (editor!=null){
-                    String json = location.toJson();
-                    editor.set(0,json);
-                    CacheLogUtils.d("SqlLiteCache-----put--json--"+json);
-                    editor.commit();
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    diskLruCache.flush();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
+        String safeKey = safeKeyGenerator.getSafeKey(url);
+        location.setUrlMd5(safeKey);
+        String json = location.toJson();
+        CacheLogUtils.d("SqlLiteCache-----put--json--"+json);
+        interDiskCache.put(url,json);
     }
 
     /**
@@ -76,34 +53,13 @@ public class SqlLiteCache {
      * @return
      */
     public synchronized long get(String url){
-        if (url==null || url.length()==0){
+        String data = interDiskCache.get(url);
+        if (data==null || data.length()==0){
             return -1;
         }
-        if (diskLruCache!=null){
-            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-            CacheLogUtils.d("SqlLiteCache-----get--key-"+key);
-            try {
-                DiskLruCache.Value value = diskLruCache.get(key);
-                if (value != null) {
-                    File file = value.getFile(0);
-                    long length = value.getLength(0);
-                    String string = value.getString(0);
-                    VideoLocation location = VideoLocation.toObject(string);
-                    long position = location.getPosition();
-                    CacheLogUtils.d("SqlLiteCache-----get---"+file+"-------"+length+"-------"+string+"-----"+position);
-                    return position;
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    diskLruCache.flush();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return -1;
+        CacheLogUtils.d("SqlLiteCache-----get---"+data);
+        VideoLocation location = VideoLocation.toObject(data);
+        return location.getPosition();
     }
 
     /**
@@ -112,22 +68,7 @@ public class SqlLiteCache {
      * @return
      */
     public synchronized boolean remove(String url){
-        if (diskLruCache!=null){
-            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-            try {
-                boolean remove = diskLruCache.remove(key);
-                return remove;
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    diskLruCache.flush();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return false;
+        return interDiskCache.remove(url);
     }
 
     /**
@@ -136,44 +77,15 @@ public class SqlLiteCache {
      * @return
      */
     public synchronized boolean containsKey(String url){
-        if (diskLruCache!=null){
-            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
-            try {
-                DiskLruCache.Value value = diskLruCache.get(key);
-                return value != null;
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    diskLruCache.flush();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return false;
+        return interDiskCache.containsKey(url);
     }
 
-
     /**
      * 清楚所有数据
      * @return                              是否清楚完毕
      */
-    public synchronized boolean clearAll(){
-        if (diskLruCache!=null){
-            try {
-                diskLruCache.delete();
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    diskLruCache.flush();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return false;
+    public synchronized void clearAll(){
+        interDiskCache.clear();
     }
 
 

+ 1 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Synthetic.java → VideoSqlLite/src/main/java/com/yc/videosqllite/disk/Synthetic.java

@@ -1,4 +1,4 @@
-package com.yc.videosqllite.disk.wrapper;
+package com.yc.videosqllite.disk;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;

+ 0 - 73
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCache.java

@@ -1,73 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.File;
-
-/**
- * An interface for writing to and reading from a disk cache.
- */
-public interface DiskCache {
-
-  /**
-   * An interface for lazily creating a disk cache.
-   */
-  interface Factory {
-    /** 250 MB of cache. */
-    int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;
-    String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
-
-    /** Returns a new disk cache, or {@code null} if no disk cache could be created. */
-    DiskCache build();
-  }
-
-  /**
-   * An interface to actually write data to a key in the disk cache.
-   */
-  interface Writer {
-    /**
-     * Writes data to the file and returns true if the write was successful and should be committed,
-     * and false if the write should be aborted.
-     *
-     * @param file The File the Writer should write to.
-     */
-    boolean write(@NonNull File file);
-  }
-
-  /**
-   * Get the cache for the value at the given key.
-   *
-   * <p> Note - This is potentially dangerous, someone may write a new value to the file at any
-   * point in time and we won't know about it. </p>
-   *
-   * @param key The key in the cache.
-   * @return An InputStream representing the data at key at the time get is called.
-   */
-  @Nullable
-  File get(Key key);
-
-  /**
-   * Write to a key in the cache. {@link Writer} is used so that the cache implementation can
-   * perform actions after the write finishes, like commit (via atomic file rename).
-   *
-   * @param key    The key to write to.
-   * @param writer An interface that will write data given an OutputStream for the key.
-   */
-  void put(Key key, Writer writer);
-
-  /**
-   * Remove the key and value from the cache.
-   *
-   * @param key The key to remove.
-   */
-  // Public API.
-  @SuppressWarnings("unused")
-  void delete(Key key);
-
-  /**
-   * Clear the cache.
-   */
-  void clear();
-}

+ 0 - 29
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheAdapter.java

@@ -1,29 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import java.io.File;
-
-/**
- * A simple class that returns null for all gets and ignores all writes.
- */
-public class DiskCacheAdapter implements DiskCache {
-  @Override
-  public File get(Key key) {
-    // no op, default for overriders
-    return null;
-  }
-
-  @Override
-  public void put(Key key, Writer writer) {
-    // no op, default for overriders
-  }
-
-  @Override
-  public void delete(Key key) {
-    // no op, default for overriders
-  }
-
-  @Override
-  public void clear() {
-      // no op, default for overriders
-  }
-}

+ 0 - 97
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheWriteLocker.java

@@ -1,97 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-
-import java.util.ArrayDeque;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Queue;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Keeps a map of keys to locks that allows locks to be removed from the map when no longer in use
- * so the size of the collection is bounded.
- *
- * <p> This class will be accessed by multiple threads in a thread pool and ensures that the
- *  number of threads interested in each lock is updated atomically so that when the count reaches
- *  0, the lock can safely be removed from the map. </p>
- */
-final class DiskCacheWriteLocker {
-  private final Map<String, WriteLock> locks = new HashMap<>();
-  private final WriteLockPool writeLockPool = new WriteLockPool();
-
-  void acquire(String safeKey) {
-    WriteLock writeLock;
-    synchronized (this) {
-      writeLock = locks.get(safeKey);
-      if (writeLock == null) {
-        writeLock = writeLockPool.obtain();
-        locks.put(safeKey, writeLock);
-      }
-      writeLock.interestedThreads++;
-    }
-
-    writeLock.lock.lock();
-  }
-
-  void release(String safeKey) {
-    WriteLock writeLock;
-    synchronized (this) {
-      writeLock = Preconditions.checkNotNull(locks.get(safeKey));
-      if (writeLock.interestedThreads < 1) {
-        throw new IllegalStateException("Cannot release a lock that is not held"
-            + ", safeKey: " + safeKey
-            + ", interestedThreads: " + writeLock.interestedThreads);
-      }
-
-      writeLock.interestedThreads--;
-      if (writeLock.interestedThreads == 0) {
-        WriteLock removed = locks.remove(safeKey);
-        if (!removed.equals(writeLock)) {
-          throw new IllegalStateException("Removed the wrong lock"
-              + ", expected to remove: " + writeLock
-              + ", but actually removed: " + removed
-              + ", safeKey: " + safeKey);
-        }
-        writeLockPool.offer(removed);
-      }
-    }
-
-    writeLock.lock.unlock();
-  }
-
-  private static class WriteLock  {
-    final Lock lock = new ReentrantLock();
-    int interestedThreads;
-
-    @Synthetic
-    WriteLock() { }
-  }
-
-  private static class WriteLockPool {
-    private static final int MAX_POOL_SIZE = 10;
-    private final Queue<WriteLock> pool = new ArrayDeque<>();
-
-    @Synthetic
-    WriteLockPool() { }
-
-    WriteLock obtain() {
-      WriteLock result;
-      synchronized (pool) {
-        result = pool.poll();
-      }
-      if (result == null) {
-        result = new WriteLock();
-      }
-      return result;
-    }
-
-    void offer(WriteLock writeLock) {
-      synchronized (pool) {
-        if (pool.size() < MAX_POOL_SIZE) {
-          pool.offer(writeLock);
-        }
-      }
-    }
-  }
-}

+ 0 - 72
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheFactory.java

@@ -1,72 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import java.io.File;
-
-/**
- * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the specified
- * disk cache directory.
- *
- * <p>If you need to make I/O access before returning the cache directory use the {@link
- * DiskLruCacheFactory#DiskLruCacheFactory(CacheDirectoryGetter, long)} constructor variant.
- */
-// Public API.
-@SuppressWarnings("unused")
-public class DiskLruCacheFactory implements DiskCache.Factory {
-  private final long diskCacheSize;
-  private final CacheDirectoryGetter cacheDirectoryGetter;
-
-  /**
-   * Interface called out of UI thread to get the cache folder.
-   */
-  public interface CacheDirectoryGetter {
-    File getCacheDirectory();
-  }
-
-  public DiskLruCacheFactory(final String diskCacheFolder, long diskCacheSize) {
-    this(new CacheDirectoryGetter() {
-      @Override
-      public File getCacheDirectory() {
-        return new File(diskCacheFolder);
-      }
-    }, diskCacheSize);
-  }
-
-  public DiskLruCacheFactory(final String diskCacheFolder, final String diskCacheName,
-                             long diskCacheSize) {
-    this(new CacheDirectoryGetter() {
-      @Override
-      public File getCacheDirectory() {
-        return new File(diskCacheFolder, diskCacheName);
-      }
-    }, diskCacheSize);
-  }
-
-  /**
-   * When using this constructor {@link CacheDirectoryGetter#getCacheDirectory()} will be called out
-   * of UI thread, allowing to do I/O access without performance impacts.
-   *
-   * @param cacheDirectoryGetter Interface called out of UI thread to get the cache folder.
-   * @param diskCacheSize        Desired max bytes size for the LRU disk cache.
-   */
-  // Public API.
-  @SuppressWarnings("WeakerAccess")
-  public DiskLruCacheFactory(CacheDirectoryGetter cacheDirectoryGetter, long diskCacheSize) {
-    this.diskCacheSize = diskCacheSize;
-    this.cacheDirectoryGetter = cacheDirectoryGetter;
-  }
-
-  @Override
-  public DiskCache build() {
-    File cacheDir = cacheDirectoryGetter.getCacheDirectory();
-
-    if (cacheDir == null) {
-      return null;
-    }
-
-    if (!cacheDir.mkdirs() && (!cacheDir.exists() || !cacheDir.isDirectory())) {
-      return null;
-    }
-
-    return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
-  }
-}

+ 0 - 182
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheWrapper.java

@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2013. Bump Technologies Inc. All Rights Reserved.
- */
-
-package com.yc.videosqllite.disk.wrapper;
-
-import android.util.Log;
-
-import com.yc.videosqllite.disk.DiskLruCache;
-import com.yc.videosqllite.disk.DiskLruCache.Value;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * The default DiskCache implementation. There must be no more than one active instance for a given
- * directory at a time.
- *
- * @see #get(File, long)
- */
-public class DiskLruCacheWrapper implements DiskCache {
-  private static final String TAG = "DiskLruCacheWrapper";
-
-  private static final int APP_VERSION = 1;
-  private static final int VALUE_COUNT = 1;
-  private static DiskLruCacheWrapper wrapper;
-
-  private final SafeKeyGenerator safeKeyGenerator;
-  private final File directory;
-  private final long maxSize;
-  private final DiskCacheWriteLocker writeLocker = new DiskCacheWriteLocker();
-  private DiskLruCache diskLruCache;
-
-  /**
-   * Get a DiskCache in the given directory and size. If a disk cache has already been created with
-   * a different directory and/or size, it will be returned instead and the new arguments will be
-   * ignored.
-   *
-   * @param directory The directory for the disk cache
-   * @param maxSize   The max size for the disk cache
-   * @return The new disk cache with the given arguments, or the current cache if one already exists
-   *
-   * @deprecated Use {@link #create(File, long)} to create a new cache with the specified arguments.
-   */
-  @SuppressWarnings("deprecation")
-  @Deprecated
-  public static synchronized DiskCache get(File directory, long maxSize) {
-    // TODO calling twice with different arguments makes it return the cache for the same
-    // directory, it's public!
-    if (wrapper == null) {
-      wrapper = new DiskLruCacheWrapper(directory, maxSize);
-    }
-    return wrapper;
-  }
-
-  /**
-   * Create a new DiskCache in the given directory with a specified max size.
-   *
-   * @param directory The directory for the disk cache
-   * @param maxSize   The max size for the disk cache
-   * @return The new disk cache with the given arguments
-   */
-  @SuppressWarnings("deprecation")
-  public static DiskCache create(File directory, long maxSize) {
-    return new DiskLruCacheWrapper(directory, maxSize);
-  }
-
-  /**
-   * @deprecated Do not extend this class.
-   */
-  @Deprecated
-  // Deprecated public API.
-  @SuppressWarnings({"WeakerAccess", "DeprecatedIsStillUsed"})
-  protected DiskLruCacheWrapper(File directory, long maxSize) {
-    this.directory = directory;
-    this.maxSize = maxSize;
-    this.safeKeyGenerator = new SafeKeyGenerator();
-  }
-
-  private synchronized DiskLruCache getDiskCache() throws IOException {
-    if (diskLruCache == null) {
-      diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
-    }
-    return diskLruCache;
-  }
-
-  @Override
-  public File get(Key key) {
-    String safeKey = safeKeyGenerator.getSafeKey(key);
-    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-      Log.v(TAG, "Get: Obtained: " + safeKey + " for for Key: " + key);
-    }
-    File result = null;
-    try {
-      // It is possible that the there will be a put in between these two gets. If so that shouldn't
-      // be a problem because we will always put the same value at the same key so our input streams
-      // will still represent the same data.
-      Value value = getDiskCache().get(safeKey);
-      if (value != null) {
-        result = value.getFile(0);
-      }
-    } catch (IOException e) {
-      if (Log.isLoggable(TAG, Log.WARN)) {
-        Log.w(TAG, "Unable to get from disk cache", e);
-      }
-    }
-    return result;
-  }
-
-  @Override
-  public void put(Key key, Writer writer) {
-    // We want to make sure that puts block so that data is available when put completes. We may
-    // actually not write any data if we find that data is written by the time we acquire the lock.
-    String safeKey = safeKeyGenerator.getSafeKey(key);
-    writeLocker.acquire(safeKey);
-    try {
-      if (Log.isLoggable(TAG, Log.VERBOSE)) {
-        Log.v(TAG, "Put: Obtained: " + safeKey + " for for Key: " + key);
-      }
-      try {
-        // We assume we only need to put once, so if data was written while we were trying to get
-        // the lock, we can simply abort.
-        DiskLruCache diskCache = getDiskCache();
-        DiskLruCache.Value current = diskCache.get(safeKey);
-        if (current != null) {
-          return;
-        }
-
-        DiskLruCache.Editor editor = diskCache.edit(safeKey);
-        if (editor == null) {
-          throw new IllegalStateException("Had two simultaneous puts for: " + safeKey);
-        }
-        try {
-          File file = editor.getFile(0);
-          if (writer.write(file)) {
-            editor.commit();
-          }
-        } finally {
-          editor.abortUnlessCommitted();
-        }
-      } catch (IOException e) {
-        if (Log.isLoggable(TAG, Log.WARN)) {
-          Log.w(TAG, "Unable to put to disk cache", e);
-        }
-      }
-    } finally {
-      writeLocker.release(safeKey);
-    }
-  }
-
-  @Override
-  public void delete(Key key) {
-    String safeKey = safeKeyGenerator.getSafeKey(key);
-    try {
-      getDiskCache().remove(safeKey);
-    } catch (IOException e) {
-      if (Log.isLoggable(TAG, Log.WARN)) {
-        Log.w(TAG, "Unable to delete from disk cache", e);
-      }
-    }
-  }
-
-  @Override
-  public synchronized void clear() {
-    try {
-      getDiskCache().delete();
-    } catch (IOException e) {
-      if (Log.isLoggable(TAG, Log.WARN)) {
-        Log.w(TAG, "Unable to clear disk cache or disk cache cleared externally", e);
-      }
-    } finally {
-      // Delete can close the cache but still throw. If we don't null out the disk cache here, every
-      // subsequent request will try to act on a closed disk cache and fail. By nulling out the disk
-      // cache we at least allow for attempts to open the cache in the future. See #2465.
-      resetDiskCache();
-    }
-  }
-
-  private synchronized void resetDiskCache() {
-    diskLruCache = null;
-  }
-}

+ 0 - 38
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalCacheDiskCacheFactory.java

@@ -1,38 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import android.content.Context;
-
-import java.io.File;
-
-
-// Public API.
-@SuppressWarnings({"unused", "WeakerAccess"})
-@Deprecated
-public final class ExternalCacheDiskCacheFactory extends DiskLruCacheFactory {
-
-  public ExternalCacheDiskCacheFactory(Context context) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
-        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
-  }
-
-  public ExternalCacheDiskCacheFactory(Context context, int diskCacheSize) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
-  }
-
-  public ExternalCacheDiskCacheFactory(final Context context, final String diskCacheName,
-      int diskCacheSize) {
-    super(new CacheDirectoryGetter() {
-      @Override
-      public File getCacheDirectory() {
-        File cacheDirectory = context.getExternalCacheDir();
-        if (cacheDirectory == null) {
-          return null;
-        }
-        if (diskCacheName != null) {
-          return new File(cacheDirectory, diskCacheName);
-        }
-        return cacheDirectory;
-      }
-    }, diskCacheSize);
-  }
-}

+ 0 - 67
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalPreferredCacheDiskCacheFactory.java

@@ -1,67 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import android.content.Context;
-
-import androidx.annotation.Nullable;
-
-import java.io.File;
-
-/**
- * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the external
- * disk cache directory, which falls back to the internal disk cache if no external storage is
- * available. If ever fell back to the internal disk cache, will use that one from that moment on.
- *
- * <p><b>Images can be read by everyone when using external disk cache.</b>
- */
-// Public API.
-@SuppressWarnings({"unused", "WeakerAccess"})
-public final class ExternalPreferredCacheDiskCacheFactory extends DiskLruCacheFactory {
-
-  public ExternalPreferredCacheDiskCacheFactory(Context context) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
-        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
-  }
-
-  public ExternalPreferredCacheDiskCacheFactory(Context context, long diskCacheSize) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
-  }
-
-  public ExternalPreferredCacheDiskCacheFactory(final Context context, final String diskCacheName,
-                                                final long diskCacheSize) {
-    super(new CacheDirectoryGetter() {
-      @Nullable
-      private File getInternalCacheDirectory() {
-        File cacheDirectory = context.getCacheDir();
-        if (cacheDirectory == null) {
-          return null;
-        }
-        if (diskCacheName != null) {
-          return new File(cacheDirectory, diskCacheName);
-        }
-        return cacheDirectory;
-      }
-
-      @Override
-      public File getCacheDirectory() {
-        File internalCacheDirectory = getInternalCacheDirectory();
-
-        // Already used internal cache, so keep using that one,
-        // thus avoiding using both external and internal with transient errors.
-        if ((null != internalCacheDirectory) && internalCacheDirectory.exists()) {
-          return internalCacheDirectory;
-        }
-
-        File cacheDirectory = context.getExternalCacheDir();
-
-        // Shared storage is not available.
-        if ((cacheDirectory == null) || (!cacheDirectory.canWrite())) {
-          return internalCacheDirectory;
-        }
-        if (diskCacheName != null) {
-          return new File(cacheDirectory, diskCacheName);
-        }
-        return cacheDirectory;
-      }
-    }, diskCacheSize);
-  }
-}

+ 0 - 40
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/InternalCacheDiskCacheFactory.java

@@ -1,40 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import android.content.Context;
-
-import java.io.File;
-
-/**
- * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the internal
- * disk cache directory.
- */
-// Public API.
-@SuppressWarnings({"WeakerAccess", "unused"})
-public final class InternalCacheDiskCacheFactory extends DiskLruCacheFactory {
-
-  public InternalCacheDiskCacheFactory(Context context) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
-        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
-  }
-
-  public InternalCacheDiskCacheFactory(Context context, long diskCacheSize) {
-    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
-  }
-
-  public InternalCacheDiskCacheFactory(final Context context, final String diskCacheName,
-                                       long diskCacheSize) {
-    super(new CacheDirectoryGetter() {
-      @Override
-      public File getCacheDirectory() {
-        File cacheDirectory = context.getCacheDir();
-        if (cacheDirectory == null) {
-          return null;
-        }
-        if (diskCacheName != null) {
-          return new File(cacheDirectory, diskCacheName);
-        }
-        return cacheDirectory;
-      }
-    }, diskCacheSize);
-  }
-}

+ 0 - 42
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Key.java

@@ -1,42 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-
-import androidx.annotation.NonNull;
-
-import java.nio.charset.Charset;
-import java.security.MessageDigest;
-
-/**
- * An interface that uniquely identifies some put of data. Implementations must implement {@link
- * Object#equals(Object)} and {@link Object#hashCode()}. Implementations are generally expected to
- * add all uniquely identifying information used in in {@link Object#equals(Object)}} and
- * {@link Object#hashCode()}} to the given {@link MessageDigest} in {@link
- * #updateDiskCacheKey(MessageDigest)}}, although this requirement is not as strict
- * for partial cache key signatures.
- */
-public interface Key {
-  String STRING_CHARSET_NAME = "UTF-8";
-  Charset CHARSET = Charset.forName(STRING_CHARSET_NAME);
-
-  /**
-   * Adds all uniquely identifying information to the given digest.
-   *
-   * <p> Note - Using {@link MessageDigest#reset()} inside of this method will result
-   * in undefined behavior. </p>
-   */
-  void updateDiskCacheKey(@NonNull MessageDigest messageDigest);
-
-  /**
-   * For caching to work correctly, implementations <em>must</em> implement this method and
-   * {@link #hashCode()}.
-   */
-  @Override
-  boolean equals(Object o);
-
-  /**
-   * For caching to work correctly, implementations <em>must</em> implement this method and
-   * {@link #equals(Object)}.
-   */
-  @Override
-  int hashCode();
-}

+ 0 - 54
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Preconditions.java

@@ -1,54 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Collection;
-
-/**
- * Contains common assertions.
- */
-public final class Preconditions {
-
-  private Preconditions() {
-    // Utility class.
-  }
-
-  public static void checkArgument(boolean expression, @NonNull String message) {
-    if (!expression) {
-      throw new IllegalArgumentException(message);
-    }
-  }
-
-  @NonNull
-  public static <T> T checkNotNull(@Nullable T arg) {
-    return checkNotNull(arg, "Argument must not be null");
-  }
-
-  @NonNull
-  public static <T> T checkNotNull(@Nullable T arg, @NonNull String message) {
-    if (arg == null) {
-      throw new NullPointerException(message);
-    }
-    return arg;
-  }
-
-  @NonNull
-  public static String checkNotEmpty(@Nullable String string) {
-    if (TextUtils.isEmpty(string)) {
-      throw new IllegalArgumentException("Must not be null or empty");
-    }
-    return string;
-  }
-
-  @NonNull
-  public static <T extends Collection<Y>, Y> T checkNotEmpty(@NonNull T collection) {
-    if (collection.isEmpty()) {
-      throw new IllegalArgumentException("Must not be empty.");
-    }
-    return collection;
-  }
-}

+ 0 - 23
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/SafeKeyGenerator.java

@@ -1,23 +0,0 @@
-package com.yc.videosqllite.disk.wrapper;
-
-import com.yc.videosqllite.cache.VideoLruCache;
-
-
-public class SafeKeyGenerator {
-
-  private final VideoLruCache<Key, String> loadIdToSafeHash = new VideoLruCache<>(1000);
-
-  public String getSafeKey(Key key) {
-    String safeKey;
-    synchronized (loadIdToSafeHash) {
-      safeKey = loadIdToSafeHash.get(key);
-    }
-    synchronized (loadIdToSafeHash) {
-      loadIdToSafeHash.put(key, safeKey);
-    }
-    return safeKey;
-  }
-
-
-
-}

+ 3 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/manager/CacheConfig.java

@@ -51,6 +51,9 @@ public class CacheConfig {
     }
 
     public int getCacheMax() {
+        if (mCacheMax<=0){
+            mCacheMax = 1000;
+        }
         return mCacheMax;
     }
 

+ 36 - 13
VideoSqlLite/src/main/java/com/yc/videosqllite/manager/LocationManager.java

@@ -17,7 +17,8 @@ import java.io.IOException;
  *     email  : yangchong211@163.com
  *     time  : 2020/8/6
  *     desc  : 音视频播放记录本地缓存
- *     revise:
+ *     revise: 最开始使用greenDao,二级缓存耗时100毫秒左右
+ *             磁盘+内存+key缓存+读写优化,耗时大概2到5毫秒左右
  * </pre>
  */
 public class LocationManager {
@@ -44,26 +45,38 @@ public class LocationManager {
      * 磁盘缓存
      */
     private SqlLiteCache sqlLiteCache;
+    /**
+     * 配置类
+     */
     private CacheConfig cacheConfig;
 
-
     private static class ManagerHolder {
-        private static final LocationManager INSTANCE = new LocationManager();
+        private static final com.yc.videosqllite.manager.LocationManager INSTANCE = new com.yc.videosqllite.manager.LocationManager();
     }
 
-    public static LocationManager getInstance() {
+    public static com.yc.videosqllite.manager.LocationManager getInstance() {
         return ManagerHolder.INSTANCE;
     }
 
     public void init(CacheConfig cacheConfig){
         this.cacheConfig = cacheConfig;
-        videoMapCache = new VideoMapCache(cacheConfig);
-        sqlLiteCache = new SqlLiteCache(cacheConfig);
         CacheLogUtils.setIsLog(cacheConfig.isLog());
+        videoMapCache = new VideoMapCache();
+        sqlLiteCache = new SqlLiteCache();
+        CacheLogUtils.d("LocationManager-----init初始化-");
+    }
+
+    public CacheConfig getCacheConfig() {
+        if (cacheConfig==null){
+            throw new RuntimeException("请先调用init方法进行初始化");
+        }
+        return cacheConfig;
     }
 
     /**
      * 存数据
+     * url为什么要md5?思考一下……
+     *
      * @param url                           链接
      * @param location                      视频数据
      */
@@ -74,6 +87,7 @@ public class LocationManager {
          * 1,表示磁盘缓存
          * 2,表示内存缓存+磁盘缓存
          */
+        long currentTimeMillis1 = System.currentTimeMillis();
         if (cacheConfig.getType() ==1){
             //存储到磁盘中
             sqlLiteCache.put(url,location);
@@ -89,6 +103,8 @@ public class LocationManager {
             //存储到内存中
             videoMapCache.put(url,location);
         }
+        long currentTimeMillis2 = System.currentTimeMillis();
+        CacheLogUtils.d("LocationManager-----put--存数据耗时-"+(currentTimeMillis2-currentTimeMillis1));
     }
 
     /**
@@ -103,6 +119,7 @@ public class LocationManager {
          * 1,表示磁盘缓存
          * 2,表示内存缓存+磁盘缓存
          */
+        long currentTimeMillis1 = System.currentTimeMillis();
         long position;
         if (cacheConfig.getType() ==1){
             //从磁盘中查找
@@ -121,6 +138,9 @@ public class LocationManager {
             //先从内存中找
             position = videoMapCache.get(url);
         }
+        long currentTimeMillis2 = System.currentTimeMillis();
+        CacheLogUtils.d("LocationManager-----get--取数据耗时-"+(currentTimeMillis2-currentTimeMillis1)
+                + "---进度-"+position);
         return position;
     }
 
@@ -182,7 +202,7 @@ public class LocationManager {
      * 清楚所有数据
      * @return                              是否清楚完毕
      */
-    public synchronized boolean clearAll(){
+    public synchronized void clearAll(){
         /*
          * type
          * 0,表示内存缓存
@@ -190,15 +210,14 @@ public class LocationManager {
          * 2,表示内存缓存+磁盘缓存
          */
         if (cacheConfig.getType() ==1){
-            return sqlLiteCache.clearAll();
+            sqlLiteCache.clearAll();
         } else if (cacheConfig.getType() ==2){
-            boolean clearAll = videoMapCache.clearAll();
-            boolean all = sqlLiteCache.clearAll();
-            return clearAll && all;
+            videoMapCache.clearAll();
+            sqlLiteCache.clearAll();
         } else if (cacheConfig.getType()==0){
-            return videoMapCache.clearAll();
+            videoMapCache.clearAll();
         } else {
-            return videoMapCache.clearAll();
+            videoMapCache.clearAll();
         }
     }
 
@@ -209,8 +228,10 @@ public class LocationManager {
     public long getUseMemory(){
         long totalMemory = Runtime.getRuntime().totalMemory();
         long freeMemory = Runtime.getRuntime().freeMemory();
+        CacheLogUtils.d("LocationManager-----内存-"+totalMemory+"-----"+freeMemory);
         //long maxMemory = Runtime.getRuntime().maxMemory();
         long useMemory = totalMemory - freeMemory;
+        CacheLogUtils.d("LocationManager-----获取当前应用使用的内存-"+useMemory);
         return useMemory;
     }
 
@@ -225,6 +246,7 @@ public class LocationManager {
         }
         long totalMemory = Runtime.getRuntime().totalMemory();
         long threshold = totalMemory / proportion;
+        CacheLogUtils.d("LocationManager-----设定内存的阈值-"+threshold);
         return threshold;
     }
 
@@ -234,6 +256,7 @@ public class LocationManager {
      */
     public void dumpHprofData(Context context){
         String dump = DiskFileUtils.getPath(context, "dump");
+        CacheLogUtils.d("LocationManager-----获取Java内存快照文件-"+dump);
         try {
             Debug.dumpHprofData(dump);
         } catch (IOException e) {

+ 49 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/model/SafeKeyGenerator.java

@@ -0,0 +1,49 @@
+package com.yc.videosqllite.model;
+
+import com.yc.videosqllite.cache.VideoLruCache;
+import com.yc.videosqllite.manager.CacheConfig;
+import com.yc.videosqllite.manager.LocationManager;
+import com.yc.videosqllite.utils.CacheLogUtils;
+import com.yc.videosqllite.utils.VideoMd5Utils;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : url校验以及缓存
+ *     revise: 内存+磁盘缓存需要md5两次,使用该类后只需要一次即可。
+ * </pre>
+ */
+public class SafeKeyGenerator {
+
+    private final VideoLruCache<Integer, String> loadIdToSafeHash = new VideoLruCache<>(1000);
+
+    public SafeKeyGenerator() {
+
+    }
+
+    public String getSafeKey(String url) {
+        if (url==null || url.length()==0){
+            return null;
+        }
+        String safeKey;
+        //获取链接的hash算法值
+        int hashCode = url.hashCode();
+        synchronized (loadIdToSafeHash) {
+            safeKey = loadIdToSafeHash.get(hashCode);
+            CacheLogUtils.d("SafeKeyGenerator-----获取缓存key-"+safeKey);
+        }
+        if (safeKey == null || safeKey.length()==0) {
+            CacheConfig cacheConfig = LocationManager.getInstance().getCacheConfig();
+            safeKey = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+            CacheLogUtils.d("SafeKeyGenerator-----md5转化key-"+safeKey);
+        }
+        synchronized (loadIdToSafeHash) {
+            loadIdToSafeHash.put(hashCode, safeKey);
+            CacheLogUtils.d("SafeKeyGenerator-----存储key-"+safeKey);
+        }
+        return safeKey;
+    }
+
+}

+ 3 - 3
VideoSqlLite/src/main/java/com/yc/videosqllite/model/VideoLocation.java

@@ -103,8 +103,8 @@ public class VideoLocation implements Serializable {
         return null;
     }
 
-    public static VideoLocation toObject(String jsonStr) {
-        VideoLocation m =  new VideoLocation();
+    public static com.yc.videosqllite.model.VideoLocation toObject(String jsonStr) {
+        com.yc.videosqllite.model.VideoLocation m =  new com.yc.videosqllite.model.VideoLocation();
         try {
             JSONObject jsonObject = new JSONObject(jsonStr);
             m.setUrl(jsonObject.has("url") ? jsonObject.getString("url"):null);
@@ -136,7 +136,7 @@ public class VideoLocation implements Serializable {
         if (o == null || getClass() != o.getClass()) {
             return false;
         }
-        VideoLocation location = (VideoLocation) o;
+        com.yc.videosqllite.model.VideoLocation location = (com.yc.videosqllite.model.VideoLocation) o;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
             return position == location.position &&
                     totalTime == location.totalTime &&

+ 1 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/utils/CacheLogUtils.java

@@ -36,7 +36,7 @@ public final class CacheLogUtils {
      * @param isLog                 是否开启日志
      */
     public static void setIsLog(boolean isLog) {
-        CacheLogUtils.isLog = isLog;
+        com.yc.videosqllite.utils.CacheLogUtils.isLog = isLog;
     }
 
     public static boolean isIsLog() {