1
0
杨充 4 жил өмнө
parent
commit
afdc6803a4

+ 1 - 3
VideoSqlLite/read/02.磁盘缓存之DiskLruCache.md

@@ -126,9 +126,7 @@
     - key将会成为缓存文件的文件名,并且必须要和图片的URL是一一对应的。那么怎样才能让key和图片的URL能够一一对应呢?直接使用URL来作为key?
     - 不太合适,因为图片URL中可能包含一些特殊字符,这些字符有可能在命名文件时是不合法的。其实最简单的做法就是将图片的URL进行MD5编码,编码后的字符串肯定是唯一的,并且只会包含0-F这样的字符,完全符合文件的命名规则。
 - 这个key为何不用字符串hash而用md5值?
-    - hash可能会出现碰撞,而md5为代表的杂凑函数几乎不可能找到碰撞。看glide源码,发现源码中使用磁盘缓存图片时,对链接也是采用md5加密得到key
-- 存和取数据需要开启子线程吗?
-
+    - hash可能会出现碰撞,而md5为代表的杂凑函数几乎不可能找到碰撞。看glide源码,发现源码中使用磁盘缓存图片时,对链接也是采用md5加密得到key?
 - 读写数据完后需要flush吗?
     - 这个方法用于将内存中的操作记录同步到日志文件(也就是journal文件)当中。这个方法非常重要,因为DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。
     - 在写入缓存操作的时候有调用过一次这个方法,但其实并不是每次写入缓存都要调用一次flush()方法的,频繁地调用并不会带来任何好处,只会额外增加同步journal文件的时间。比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了。

+ 15 - 9
VideoSqlLite/read/04.LruCache源码分析.md

@@ -10,26 +10,32 @@
     - 2.5 get源码分析
 
 
+### 00.二级缓存应用实践
+- 关于视频播放位置本地记录
+- 为何有该需求
+    - 主要是公司开发多个定制平板教育app,由于服务端没有做视频播放位置存储功能,为完成任务最后采用本地记录视频播放位置。最好是服务端记录播放位置……
+- 如何做技术选型
+    - 采用二级缓存,内存缓存和磁盘缓存。关于磁盘缓存,刚开始想着使用sql或者greenDao或者realm数据库,考虑到做成封装库,故要求体积小,尽量不依赖三方库还要效率高,因此磁盘缓存采用DiskLruCache。具体使用看api文档……
+- 代码地址
+    - https://github.com/yangchong211/YCVideoPlayer
 
 
 
-### 01.图片缓存策略
-#### 1.1 两级缓存
-- 现在主流的app中图片等资源的缓存策略一般是分两级,一个是内存级别的缓存,一个是磁盘级别的缓存。
-- 作为android系统的维护者google也开源了其缓存方案,LruCache和DiskLruCache。
-    - 从android3.1开始LruCache已经作为android源码的一部分维护在android系统中,为了兼容以前的版本android的support-v4包也提供了LruCache的维护,如果App需要兼容到android3.1之前的版本就需要使用support-v4包中的LruCache,如果不需要兼容到android3.1则直接使用android源码中的LruCache即可。
-    - 需要注意的是DiskLruCache并不是android源码的一部分。
-
 
-#### 1.2 LruCache介绍
+### 01.图片缓存策略
+#### 1.1 LruCache介绍
 - 在LruCache的源码中,关于LruCache有这样的一段介绍:
     - cache对象通过一个强引用来访问内容。每次当一个item被访问到的时候,这个item就会被移动到一个队列的队首。当一个item被添加到已经满了的队列时,这个队列的队尾的item就会被移除。
     ```
     A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.
     ```
 
-#### 1.3 LruCache核心思想
+
+#### 1.2 LruCache核心思想
 - LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存,其核心思想都是LRU缓存算法。
+    - ![image](https://img-blog.csdnimg.cn/20210207165359999.png)
+- LruCache的淘汰策略简单说明
+    - 将LinkedHashMap中的默认顺序设置为访问顺序,每次调用get,则将该对象移到链表的头部,调用put插入新的对象到链表头部。当内存缓存达到最大值时,就将链表尾部的对象移除。每次put或者remove,都需要判断缓存大小是否足够trimToSize。
 
 
 

+ 8 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/cache/SystemLruCache.java

@@ -2,6 +2,7 @@ package com.yc.videosqllite.cache;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -37,6 +38,7 @@ public class SystemLruCache<K, V> {
             throw new IllegalArgumentException("maxSize <= 0");
         }
         this.maxSize = maxSize;
+        //创建map集合
         this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
     }
 
@@ -145,10 +147,12 @@ public class SystemLruCache<K, V> {
      *     to evict even 0-sized elements.
      */
     private void trimToSize(int maxSize) {
+        //循环遍历
         while (true) {
             K key;
             V value;
             synchronized (this) {
+                //如果为空,则抛出异常
                 if (size < 0 || (map.isEmpty() && size != 0)) {
                     throw new IllegalStateException(getClass().getName()
                             + ".sizeOf() is reporting inconsistent results!");
@@ -163,7 +167,8 @@ public class SystemLruCache<K, V> {
                 // This is not efficient, the goal here is to minimize the changes
                 // compared to the platform version.
                 Map.Entry<K, V> toEvict = null;
-                for (Map.Entry<K, V> entry : map.entrySet()) {
+                Set<Map.Entry<K, V>> entries = map.entrySet();
+                for (Map.Entry<K, V> entry : entries) {
                     toEvict = entry;
                 }
                 // END LAYOUTLIB CHANGE
@@ -174,7 +179,9 @@ public class SystemLruCache<K, V> {
 
                 key = toEvict.getKey();
                 value = toEvict.getValue();
+                //移除
                 map.remove(key);
+                //逐次减去1
                 size -= safeSizeOf(key, value);
                 evictionCount++;
             }