The cache stores its data in a directory on the filesystem. This 53 | * directory must be exclusive to the cache; the cache may delete or overwrite 54 | * files from its directory. It is an error for multiple processes to use the 55 | * same cache directory at the same time. 56 | *
57 | *This cache limits the number of bytes that it will store on the 58 | * filesystem. When the number of stored bytes exceeds the limit, the cache will 59 | * remove entries in the background until the limit is satisfied. The limit is 60 | * not strict: the cache may temporarily exceed it while waiting for files to be 61 | * deleted. The limit does not include filesystem overhead or the cache 62 | * journal so space-sensitive applications should set a conservative limit. 63 | *
64 | *Clients call {@link #edit} to create or update the values of an entry. An 65 | * entry may have only one editor at one time; if a value is not available to be 66 | * edited then {@link #edit} will return null. 67 | *
Clients call {@link #get} to read a snapshot of an entry. The read will 80 | * observe the value at the time that {@link #get} was called. Updates and 81 | * removals after the call do not impact ongoing reads. 82 | *
83 | *This class is tolerant of some I/O errors. If files are missing from the
84 | * filesystem, the corresponding entries will be dropped from the cache. If
85 | * an error occurs while writing a cache value, the edit will fail silently.
86 | * Callers should handle other problems by catching {@code IOException} and
87 | * responding appropriately.
88 | */
89 | public final class DiskLruCache implements Closeable {
90 | static final String JOURNAL_FILE = "journal";
91 | static final String JOURNAL_FILE_TEMP = "journal.tmp";
92 | static final String JOURNAL_FILE_BACKUP = "journal.bkp";
93 | static final String MAGIC = "libcore.io.DiskLruCache";
94 | static final String VERSION_1 = "1";
95 | static final long ANY_SEQUENCE_NUMBER = -1;
96 | static final String STRING_KEY_PATTERN = "[a-z0-9_-]{1,120}";
97 | static final Pattern LEGAL_KEY_PATTERN = Pattern.compile(STRING_KEY_PATTERN);
98 | private static final String CLEAN = "CLEAN";
99 | private static final String DIRTY = "DIRTY";
100 | private static final String REMOVE = "REMOVE";
101 | private static final String READ = "READ";
102 |
103 | /*
104 | * This cache uses a journal file named "journal". A typical journal file
105 | * looks like this:
106 | * libcore.io.DiskLruCache
107 | * 1
108 | * 100
109 | * 2
110 | *
111 | * CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
112 | * DIRTY 335c4c6028171cfddfbaae1a9c313c52
113 | * CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
114 | * REMOVE 335c4c6028171cfddfbaae1a9c313c52
115 | * DIRTY 1ab96a171faeeee38496d8b330771a7a
116 | * CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
117 | * READ 335c4c6028171cfddfbaae1a9c313c52
118 | * READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
119 | *
120 | * The first five lines of the journal form its header. They are the
121 | * constant string "libcore.io.DiskLruCache", the disk cache's version,
122 | * the application's version, the value count, and a blank line.
123 | *
124 | * Each of the subsequent lines in the file is a record of the state of a
125 | * cache entry. Each line contains space-separated values: a state, a key,
126 | * and optional state-specific values.
127 | * o DIRTY lines track that an entry is actively being created or updated.
128 | * Every successful DIRTY action should be followed by a CLEAN or REMOVE
129 | * action. DIRTY lines without a matching CLEAN or REMOVE indicate that
130 | * temporary files may need to be deleted.
131 | * o CLEAN lines track a cache entry that has been successfully published
132 | * and may be read. A publish line is followed by the lengths of each of
133 | * its values.
134 | * o READ lines track accesses for LRU.
135 | * o REMOVE lines track entries that have been deleted.
136 | *
137 | * The journal file is appended to as cache operations occur. The journal may
138 | * occasionally be compacted by dropping redundant lines. A temporary file named
139 | * "journal.tmp" will be used during compaction; that file should be deleted if
140 | * it exists when the cache is opened.
141 | */
142 |
143 | private final File directory;
144 | private final File journalFile;
145 | private final File journalFileTmp;
146 | private final File journalFileBackup;
147 | private final int appVersion;
148 | private long maxSize;
149 | private final int valueCount;
150 | private long size = 0;
151 | private Writer journalWriter;
152 | private final LinkedHashMap This class is used for buffered reading of lines. For purposes of this class, a line ends
31 | * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
32 | * line at end of input is invalid and will be ignored, the caller may use {@code
33 | * hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
34 | *
35 | * This class is intended for reading input that strictly consists of lines, such as line-based
36 | * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
37 | * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
38 | * end-of-input reporting and a more restrictive definition of a line.
39 | *
40 | * This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
41 | * and 10, respectively, and the representation of no other character contains these values.
42 | * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
43 | * The default charset is US_ASCII.
44 | */
45 | class StrictLineReader implements Closeable {
46 | private static final byte CR = (byte) '\r';
47 | private static final byte LF = (byte) '\n';
48 |
49 | private final InputStream in;
50 | private final Charset charset;
51 |
52 | /*
53 | * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
54 | * and the data in the range [pos, end) is buffered for reading. At end of input, if there is
55 | * an unterminated line, we set end == -1, otherwise end == pos. If the underlying
56 | * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
57 | */
58 | private byte[] buf;
59 | private int pos;
60 | private int end;
61 |
62 | /**
63 | * Constructs a new {@code LineReader} with the specified charset and the default capacity.
64 | *
65 | * @param in the {@code InputStream} to read data from.
66 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
67 | * supported.
68 | * @throws NullPointerException if {@code in} or {@code charset} is null.
69 | * @throws IllegalArgumentException if the specified charset is not supported.
70 | */
71 | public StrictLineReader(InputStream in, Charset charset) {
72 | this(in, 8192, charset);
73 | }
74 |
75 | /**
76 | * Constructs a new {@code LineReader} with the specified capacity and charset.
77 | *
78 | * @param in the {@code InputStream} to read data from.
79 | * @param capacity the capacity of the buffer.
80 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
81 | * supported.
82 | * @throws NullPointerException if {@code in} or {@code charset} is null.
83 | * @throws IllegalArgumentException if {@code capacity} is negative or zero
84 | * or the specified charset is not supported.
85 | */
86 | public StrictLineReader(InputStream in, int capacity, Charset charset) {
87 | if (in == null || charset == null) {
88 | throw new NullPointerException();
89 | }
90 | if (capacity < 0) {
91 | throw new IllegalArgumentException("capacity <= 0");
92 | }
93 | if (!(charset.equals(Util.US_ASCII))) {
94 | throw new IllegalArgumentException("Unsupported encoding");
95 | }
96 |
97 | this.in = in;
98 | this.charset = charset;
99 | buf = new byte[capacity];
100 | }
101 |
102 | /**
103 | * Closes the reader by closing the underlying {@code InputStream} and
104 | * marking this reader as closed.
105 | *
106 | * @throws IOException for errors when closing the underlying {@code InputStream}.
107 | */
108 | public void close() throws IOException {
109 | synchronized (in) {
110 | if (buf != null) {
111 | buf = null;
112 | in.close();
113 | }
114 | }
115 | }
116 |
117 | /**
118 | * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
119 | * this end of line marker is not included in the result.
120 | *
121 | * @return the next line from the input.
122 | * @throws IOException for underlying {@code InputStream} errors.
123 | * @throws EOFException for the end of source stream.
124 | */
125 | public String readLine() throws IOException {
126 | synchronized (in) {
127 | if (buf == null) {
128 | throw new IOException("LineReader is closed");
129 | }
130 |
131 | // Read more data if we are at the end of the buffered data.
132 | // Though it's an error to read after an exception, we will let {@code fillBuf()}
133 | // throw again if that happens; thus we need to handle end == -1 as well as end == pos.
134 | if (pos >= end) {
135 | fillBuf();
136 | }
137 | // Try to find LF in the buffered data and return the line if successful.
138 | for (int i = pos; i != end; ++i) {
139 | if (buf[i] == LF) {
140 | int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
141 | String res = new String(buf, pos, lineEnd - pos, charset.name());
142 | pos = i + 1;
143 | return res;
144 | }
145 | }
146 |
147 | // Let's anticipate up to 80 characters on top of those already read.
148 | ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
149 | @Override
150 | public String toString() {
151 | int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
152 | try {
153 | return new String(buf, 0, length, charset.name());
154 | } catch (UnsupportedEncodingException e) {
155 | throw new AssertionError(e); // Since we control the charset this will never happen.
156 | }
157 | }
158 | };
159 |
160 | while (true) {
161 | out.write(buf, pos, end - pos);
162 | // Mark unterminated line in case fillBuf throws EOFException or IOException.
163 | end = -1;
164 | fillBuf();
165 | // Try to find LF in the buffered data and return the line if successful.
166 | for (int i = pos; i != end; ++i) {
167 | if (buf[i] == LF) {
168 | if (i != pos) {
169 | out.write(buf, pos, i - pos);
170 | }
171 | pos = i + 1;
172 | return out.toString();
173 | }
174 | }
175 | }
176 | }
177 | }
178 |
179 | public boolean hasUnterminatedLine() {
180 | return end == -1;
181 | }
182 |
183 | /**
184 | * Reads new input data into the buffer. Call only with pos == end or end == -1,
185 | * depending on the desired outcome if the function throws.
186 | */
187 | private void fillBuf() throws IOException {
188 | int result = in.read(buf, 0, buf.length);
189 | if (result == -1) {
190 | throw new EOFException();
191 | }
192 | pos = 0;
193 | end = result;
194 | }
195 | }
196 |
197 |
--------------------------------------------------------------------------------
/app/src/main/java/com/softtanck/imageloader/imageloader/disklrucahe/Util.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.softtanck.imageloader.imageloader.disklrucahe;
18 |
19 | import java.io.Closeable;
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.io.Reader;
23 | import java.io.StringWriter;
24 | import java.nio.charset.Charset;
25 |
26 | /**
27 | * Junk drawer of utility methods.
28 | */
29 | final class Util {
30 | static final Charset US_ASCII = Charset.forName("US-ASCII");
31 | static final Charset UTF_8 = Charset.forName("UTF-8");
32 |
33 | private Util() {
34 | }
35 |
36 | static String readFully(Reader reader) throws IOException {
37 | try {
38 | StringWriter writer = new StringWriter();
39 | char[] buffer = new char[1024];
40 | int count;
41 | while ((count = reader.read(buffer)) != -1) {
42 | writer.write(buffer, 0, count);
43 | }
44 | return writer.toString();
45 | } finally {
46 | reader.close();
47 | }
48 | }
49 |
50 | /**
51 | * Deletes the contents of {@code dir}. Throws an IOException if any file
52 | * could not be deleted, or if {@code dir} is not a readable directory.
53 | */
54 | static void deleteContents(File dir) throws IOException {
55 | File[] files = dir.listFiles();
56 | if (files == null) {
57 | throw new IOException("not a readable directory: " + dir);
58 | }
59 | for (File file : files) {
60 | if (file.isDirectory()) {
61 | deleteContents(file);
62 | }
63 | if (!file.delete()) {
64 | throw new IOException("failed to delete file: " + file);
65 | }
66 | }
67 | }
68 |
69 | static void closeQuietly(/*Auto*/Closeable closeable) {
70 | if (closeable != null) {
71 | try {
72 | closeable.close();
73 | } catch (RuntimeException rethrown) {
74 | throw rethrown;
75 | } catch (Exception ignored) {
76 | }
77 | }
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/softtanck/imageloader/imageloader/listener/AnimListener.java:
--------------------------------------------------------------------------------
1 | package com.softtanck.imageloader.imageloader.listener;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * @author : Tanck
7 | * @Description : TODO 动画接口类
8 | * @date 10/20/2015
9 | */
10 | public interface AnimListener {
11 |
12 | /**
13 | * 获取动画视图
14 | *
15 | * @return
16 | */
17 | public View getAnimView();
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/softtanck/imageloader/imageloader/listener/LoadListener.java:
--------------------------------------------------------------------------------
1 | package com.softtanck.imageloader.imageloader.listener;
2 |
3 | import android.graphics.Bitmap;
4 | import android.view.View;
5 |
6 | /**
7 | * @author : Tanck
8 | * @Description : TODO 图片加载接口
9 | * @date 10/20/2015
10 | */
11 | public interface LoadListener