浏览代码

完善二级缓存

杨充 4 年之前
父节点
当前提交
f565f54aa1

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

@@ -131,8 +131,7 @@
 
 - 读写数据完后需要flush吗?
     - 这个方法用于将内存中的操作记录同步到日志文件(也就是journal文件)当中。这个方法非常重要,因为DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。
-    - 在写入缓存操作的时候有调用过一次这个方法,但其实并不是每次写入缓存都要调用一次flush()方法的,频繁地调用并不会带来任何好处,只会额外增加同步journal文件的时间。
-    - 比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了。
+    - 在写入缓存操作的时候有调用过一次这个方法,但其实并不是每次写入缓存都要调用一次flush()方法的,频繁地调用并不会带来任何好处,只会额外增加同步journal文件的时间。比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了。
 - 移除缓存remove需要手动调用吗?
     - remove()方法中要求传入一个key,然后会删除这个key对应的缓存图片。用法虽然简单,但是你要知道,这个方法我们并不应该经常去调用它。
     - 因为你完全不需要担心缓存的数据过多从而占用SD卡太多空间的问题,DiskLruCache会根据我们在调用open()方法时设定的缓存最大值来自动删除多余的缓存。只有你确定某个key对应的缓存内容已经过期,需要从网络获取最新数据的时候才应该调用remove()方法来移除缓存。

+ 5 - 1
VideoSqlLite/read/05.DiskLruCache源码分析.md

@@ -261,7 +261,11 @@ new LinkedHashMap<String, Entry>(0, 0.75f, true); ),此时 lruEntries 里没
         }
     }
     ```
-- journal 日志每一行中的各个部分都是用 ' ' 空格来分割的,所以先用 空格来截取一下。拿到 key,然后判断 firstSpace 是 REMOVE 就会调用 lruEntries.remove(key); ,若不是 REMOVE ,如果该 key 没有加入到 lruEntries ,则创建并且加入。然后继续判断 firstSpace ,若是 CLEAN ,则初始化 entry ,设置 readable=true , currentEditor 为 null ,初始化长度等。若是 DIRTY ,则设置 currentEditor 对象。若是 READ,无操作。
+- journal 日志每一行中的各个部分都是用 ' ' 空格来分割的,所以先用 空格来截取一下。
+    - 拿到 key,然后判断 firstSpace 是 REMOVE 就会调用 lruEntries.remove(key); ,若不是 REMOVE ,如果该 key 没有加入到 lruEntries ,则创建并且加入。
+    - 然后继续判断 firstSpace ,若是 CLEAN ,则初始化 entry ,设置 readable=true , currentEditor 为 null ,初始化长度等。
+    - 若是 DIRTY ,则设置 currentEditor 对象。
+    - 若是 READ,无操作。
 - 一般正常操作下 DIRTY 不会单独出现,会和 REMOVE or CLEAN 成对出现;经过上面这个流程,基本上加入到 lruEntries 里面的只有 CLEAN 且没有被 REMOVE 的 key。
 - 然后我们回到 readJournal 方法,在我们按行读取的时候,会记录一下 lineCount ,然后赋值给 redundantOpCount ,该变量记录的是多余的记录条数( redundantOpCount = lineCount - lruEntries.size(); 文件的行数-真正可以的 key 的行数)。最后,如果读取过程中发现 journal 文件有问题,则重建 journal 文件。没有问题的话,初始化下 journalWriter,关闭 reader。
 - 我们再回到 open() 方法中,readJournal 完成了,会继续调用 processJournal() 这个方法

+ 39 - 6
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCache.java

@@ -68,9 +68,22 @@ public final class DiskLruCache implements Closeable {
     static final String MAGIC = "libcore.io.DiskLruCache";
     static final String VERSION_1 = "1";
     static final long ANY_SEQUENCE_NUMBER = -1;
+    /**
+     * 该状态表示一个缓存Entry已经被成功发布了并且可以读取,该行后面会有每个Value的大小。
+     */
     private static final String CLEAN = "CLEAN";
+    /**
+     * 该状态表示一个Entry正在被创建或正在被更新,任意一个成功的DIRTY操作后面都会有一个CLEAN或REMOVE操作。
+     * 如果一个DIRTY操作后面没有CLEAN或者REMOVE操作,那就表示这是一个临时文件,应该将其删除。
+     */
     private static final String DIRTY = "DIRTY";
+    /**
+     * 表示被删除的缓存Entry。
+     */
     private static final String REMOVE = "REMOVE";
+    /**
+     * 在LRU缓存中被读取了。
+     */
     private static final String READ = "READ";
 
     private final File directory;
@@ -261,35 +274,43 @@ public final class DiskLruCache implements Closeable {
         }
 
         int keyBegin = firstSpace + 1;
+        //journal 日志每一行中的各个部分都是用 ' ' 空格来分割的,所以先用 空格来截取一下
         int secondSpace = line.indexOf(' ', keyBegin);
         final String key;
         if (secondSpace == -1) {
+            //拿到 key
             key = line.substring(keyBegin);
             // 如果是REMOVE,则将该key代表的缓存从lruEntries中移除
             if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
+                //然后判断 firstSpace 是 REMOVE 就会调用 lruEntries.remove(key)
                 lruEntries.remove(key);
                 return;
             }
         } else {
+            //拿到 key
             key = line.substring(keyBegin, secondSpace);
         }
 
         //取出当前key对应的缓存Entry
         Entry entry = lruEntries.get(key);
         if (entry == null) {
+            //若不是 REMOVE ,如果该 key 没有加入到 lruEntries ,则创建并且加入
             entry = new Entry(key);
             lruEntries.put(key, entry);
         }
         // 如果是CLEAN、DIRTY或READ
         if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
+            //继续判断 firstSpace ,若是 CLEAN ,则初始化 entry ,设置 readable=true , currentEditor 为 null ,初始化长度等。
             String[] parts = line.substring(secondSpace + 1).split(" ");
             entry.readable = true;
             entry.currentEditor = null;
             entry.setLengths(parts);
         } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
+            //若是 DIRTY ,则设置 currentEditor 对象。
             entry.currentEditor = new Editor(entry);
         } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
             // This work was already done by calling lruEntries.get().
+            //若是 READ,无操作。
         } else {
             throw new IOException("unexpected journal line: " + line);
         }
@@ -326,21 +347,32 @@ public final class DiskLruCache implements Closeable {
             journalWriter.close();
         }
 
-        Writer writer = new BufferedWriter(
-                new OutputStreamWriter(new FileOutputStream(journalFileTmp), DiskUtils.US_ASCII));
+        FileOutputStream fileOutputStream = new FileOutputStream(journalFileTmp);
+        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, DiskUtils.US_ASCII);
+        //高效字符流
+        Writer writer = new BufferedWriter(outputStreamWriter);
         try {
+            //这一块是写入头部的5行
+            //libcore.io.DiskLruCache 是固定字符串,表明使用的是 DiskLruCache 技术;
             writer.write(MAGIC);
             writer.write("\n");
+            //DiskLruCache 的版本号,源码中为常量 1;
             writer.write(VERSION_1);
             writer.write("\n");
+            //APP 的版本号,即我们在 open() 方法里传入的版本号;
             writer.write(Integer.toString(appVersion));
             writer.write("\n");
+            //valueCount,这个值也是在 open() 方法中传入的,指每个 key 对应几个文件,通常情况下都为 1;
             writer.write(Integer.toString(valueCount));
             writer.write("\n");
+            //空行
             writer.write("\n");
 
             for (Entry entry : lruEntries.values()) {
                 if (entry.currentEditor != null) {
+                    //看到DIRTY这个字样都不代表着什么好事情,意味着这是一条脏数据。
+                    //没错,每当我们调用一次DiskLruCache的edit()方法时,都会向journal文件中写入一条DIRTY记录,
+                    //表示我们正准备写入一条缓存数据,但不知结果如何。
                     writer.write(DIRTY + ' ' + entry.key + '\n');
                 } else {
                     writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
@@ -570,6 +602,7 @@ public final class DiskLruCache implements Closeable {
 
     /**
      * 只有当日志大小减半并消除至少2000个ops时,我们才重新生成日志。
+     * 在写入数据,获取数据或者移除数据时都会做校验
      */
     private boolean journalRebuildRequired() {
         final int redundantOpCompactThreshold = 2000;
@@ -834,7 +867,7 @@ public final class DiskLruCache implements Closeable {
         private final String key;
 
         /**
-         * Lengths of this entry's files.
+         * 条目的文件长度
          */
         private final long[] lengths;
 
@@ -845,17 +878,17 @@ public final class DiskLruCache implements Closeable {
         File[] dirtyFiles;
 
         /**
-         * True if this entry has ever been published.
+         * 如果这个条目曾经被发表过,则为真。
          */
         private boolean readable;
 
         /**
-         * The ongoing edit or null if this entry is not being edited.
+         * 正在进行的编辑,如果该条目没有被编辑,则为空。
          */
         private Editor currentEditor;
 
         /**
-         * The sequence number of the most recently committed edit to this entry.
+         * 最近提交到该条目的编辑的序列号
          */
         private long sequenceNumber;
 

+ 9 - 32
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/StrictLineReader.java

@@ -1,18 +1,3 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 
 package com.yc.videosqllite.disk;
 
@@ -24,25 +9,17 @@ import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 
+
 /**
- * Buffers input from an {@link InputStream} for reading lines.
- *
- * <p>This class is used for buffered reading of lines. For purposes of this class, a line ends
- * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
- * line at end of input is invalid and will be ignored, the caller may use {@code
- * hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
- *
- * <p>This class is intended for reading input that strictly consists of lines, such as line-based
- * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
- * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
- * end-of-input reporting and a more restrictive definition of a line.
- *
- * <p>This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
- * and 10, respectively, and the representation of no other character contains these values.
- * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
- * The default charset is US_ASCII.
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 缓冲区来自{@link InputStream}的输入用于读取行
+ *     revise:
+ * </pre>
  */
-class StrictLineReader implements Closeable {
+public class StrictLineReader implements Closeable {
     private static final byte CR = (byte) '\r';
     private static final byte LF = (byte) '\n';
 

+ 18 - 3
read/03.视频播放器Api说明.md

@@ -16,6 +16,7 @@
 - 14.视频播放器埋点
 - 15.关于视频配置
 - 16.视频播放位置本地缓存
+- 17.关于混淆说明
 
 
 
@@ -691,9 +692,23 @@
     ```
 
 
-
-
-
+### 17.关于混淆说明
+- 混淆如下所示
+```
+# 视频播放器
+# 视频内核
+-keep class com.yc.kernel.**{*;}
+# 视频播放器
+-keep class com.yc.video.**{*;}
+# 视频缓存
+-keep class com.yc.videocache.**{*;}
+# 视频悬浮view
+-keep class com.yc.videoview.**{*;}
+# 视频位置记录
+-keep class com.yc.videosqllite.**{*;}
+# 视频m3u8分片下载和合成
+-keep class com.yc.m3u8.**{*;}
+```