Reformat code
This commit is contained in:
1 parent
36aa37359b
commit
622d4055d9
25 files changed
+1158
-1123
No files matched your search
@@ -33,15 +33,13 @@ import java.io.OutputStream;
|
||||
public abstract class BeerBelly<V> {
|
||||
|
||||
private static final String TAG = BeerBelly.class.getSimpleName();
|
||||
|
||||
private final boolean mHasMemoryCache;
|
||||
private final boolean mHasDiskCache;
|
||||
@Nullable
|
||||
private MemoryCache<V> mMemoryCache;
|
||||
@Nullable
|
||||
private DiskCache<V> mDiskCache;
|
||||
|
||||
private final boolean mHasMemoryCache;
|
||||
private final boolean mHasDiskCache;
|
||||
|
||||
public BeerBelly(BeerBellyParams params) {
|
||||
params.isValid();
|
||||
mHasMemoryCache = params.hasMemoryCache;
|
||||
@@ -220,7 +218,7 @@ public abstract class BeerBelly<V> {
|
||||
/**
|
||||
* Put value to memory cache
|
||||
*
|
||||
* @param key the key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return false if no memory cache
|
||||
*/
|
||||
@@ -237,7 +235,7 @@ public abstract class BeerBelly<V> {
|
||||
/**
|
||||
* Put value to disk cache
|
||||
*
|
||||
* @param key the key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return false if no disk cache or get error
|
||||
*/
|
||||
@@ -252,7 +250,7 @@ public abstract class BeerBelly<V> {
|
||||
/**
|
||||
* Put value to memory cache and disk cache
|
||||
*
|
||||
* @param key the key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
*/
|
||||
public void put(@NonNull String key, @NonNull V value) {
|
||||
@@ -286,9 +284,8 @@ public abstract class BeerBelly<V> {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key the key
|
||||
* @param is the input stream to store
|
||||
* @param is the input stream to store
|
||||
* @return false if no disk cache or get error
|
||||
*/
|
||||
public boolean putRawToDisk(@NonNull String key, @NonNull InputStream is) {
|
||||
@@ -381,26 +378,6 @@ public abstract class BeerBelly<V> {
|
||||
}
|
||||
}
|
||||
|
||||
private class MemoryCache<E> extends LruCache<String, E> {
|
||||
|
||||
public BeerBelly<E> mParent;
|
||||
|
||||
public MemoryCache(int maxSize, BeerBelly<E> parent) {
|
||||
super(maxSize);
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int sizeOf(String key, E value) {
|
||||
return mParent.sizeOf(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entryRemoved(boolean evicted, String key, E oldValue, E newValue) {
|
||||
mParent.memoryEntryRemoved(evicted, key, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DiskCache<E> {
|
||||
|
||||
private static final int IO_BUFFER_SIZE = 8 * 1024;
|
||||
@@ -492,4 +469,24 @@ public abstract class BeerBelly<V> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MemoryCache<E> extends LruCache<String, E> {
|
||||
|
||||
public BeerBelly<E> mParent;
|
||||
|
||||
public MemoryCache(int maxSize, BeerBelly<E> parent) {
|
||||
super(maxSize);
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int sizeOf(String key, E value) {
|
||||
return mParent.sizeOf(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entryRemoved(boolean evicted, String key, E oldValue, E newValue) {
|
||||
mParent.memoryEntryRemoved(evicted, key, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -33,7 +33,9 @@ import java.util.Map;
|
||||
public class LruCache<K, V> {
|
||||
private final LinkedHashMap<K, V> map;
|
||||
|
||||
/** Size of this cache in units. Not necessarily the number of elements. */
|
||||
/**
|
||||
* Size of this cache in units. Not necessarily the number of elements.
|
||||
*/
|
||||
private int size;
|
||||
private int maxSize;
|
||||
|
||||
@@ -45,8 +47,8 @@ public class LruCache<K, V> {
|
||||
|
||||
/**
|
||||
* @param maxSize for caches that do not override {@link #sizeOf}, this is
|
||||
* the maximum number of entries in the cache. For all other caches,
|
||||
* this is the maximum sum of the sizes of the entries in this cache.
|
||||
* the maximum number of entries in the cache. For all other caches,
|
||||
* this is the maximum sum of the sizes of the entries in this cache.
|
||||
*/
|
||||
public LruCache(int maxSize) {
|
||||
if (maxSize <= 0) {
|
||||
@@ -171,7 +173,7 @@ public class LruCache<K, V> {
|
||||
* below the requested size.
|
||||
*
|
||||
* @param maxSize the maximum size of the cache before returning. May be -1
|
||||
* to evict even 0-sized elements.
|
||||
* to evict even 0-sized elements.
|
||||
*/
|
||||
public void trimToSize(int maxSize) {
|
||||
while (true) {
|
||||
@@ -233,13 +235,14 @@ public class LruCache<K, V> {
|
||||
* <p>The method is called without synchronization: other threads may
|
||||
* access the cache while this method is executing.
|
||||
*
|
||||
* @param evicted true if the entry is being removed to make space, false
|
||||
* if the removal was caused by a {@link #put} or {@link #remove}.
|
||||
* @param evicted true if the entry is being removed to make space, false
|
||||
* if the removal was caused by a {@link #put} or {@link #remove}.
|
||||
* @param newValue the new value for {@code key}, if it exists. If non-null,
|
||||
* this removal was caused by a {@link #put}. Otherwise it was caused by
|
||||
* an eviction or a {@link #remove}.
|
||||
* this removal was caused by a {@link #put}. Otherwise it was caused by
|
||||
* an eviction or a {@link #remove}.
|
||||
*/
|
||||
protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
|
||||
protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after a cache miss to compute a value for the corresponding key.
|
||||
@@ -351,7 +354,8 @@ public class LruCache<K, V> {
|
||||
|
||||
@NonNull
|
||||
@SuppressLint("DefaultLocale")
|
||||
@Override public synchronized final String toString() {
|
||||
@Override
|
||||
public synchronized final String toString() {
|
||||
int accesses = hitCount + missCount;
|
||||
int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
|
||||
return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
|
||||
|
||||
@@ -55,15 +55,13 @@ public class SimpleDiskCache {
|
||||
|
||||
private final File mCacheDir;
|
||||
private final int mSize;
|
||||
|
||||
private int mDiskCacheState;
|
||||
|
||||
@Nullable
|
||||
private DiskLruCache mDiskLruCache;
|
||||
@NonNull
|
||||
private final Map<String, CounterLock> mLockMap = new HashMap<>();
|
||||
@NonNull
|
||||
private final LockPool mLockPool = new LockPool();
|
||||
private int mDiskCacheState;
|
||||
@Nullable
|
||||
private DiskLruCache mDiskLruCache;
|
||||
|
||||
public SimpleDiskCache(File cacheDir, int size) {
|
||||
mCacheDir = cacheDir;
|
||||
@@ -76,6 +74,43 @@ public class SimpleDiskCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A hashing method that changes a string (like a URL) into a hash suitable
|
||||
* for using as a disk filename.
|
||||
*
|
||||
* @param key The key used to store the file
|
||||
*/
|
||||
private static String hashKeyForDisk(final String key) {
|
||||
String cacheKey;
|
||||
try {
|
||||
final MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digest.update(key.getBytes());
|
||||
cacheKey = bytesToHexString(digest.digest());
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
cacheKey = String.valueOf(key.hashCode());
|
||||
}
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/332079
|
||||
*
|
||||
* @param bytes The bytes to convert.
|
||||
* @return A {@link String} converted from the bytes of a hashable key used
|
||||
* to store a filename on the disk, to hex digits.
|
||||
*/
|
||||
private static String bytesToHexString(final byte[] bytes) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final byte b : bytes) {
|
||||
final String hex = Integer.toHexString(0xFF & b);
|
||||
if (hex.length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(hex);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public synchronized boolean isValid() {
|
||||
return mDiskLruCache != null;
|
||||
}
|
||||
@@ -303,43 +338,6 @@ public class SimpleDiskCache {
|
||||
return new CacheOutputStreamPipe(diskKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* A hashing method that changes a string (like a URL) into a hash suitable
|
||||
* for using as a disk filename.
|
||||
*
|
||||
* @param key The key used to store the file
|
||||
*/
|
||||
private static String hashKeyForDisk(final String key) {
|
||||
String cacheKey;
|
||||
try {
|
||||
final MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digest.update(key.getBytes());
|
||||
cacheKey = bytesToHexString(digest.digest());
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
cacheKey = String.valueOf(key.hashCode());
|
||||
}
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/332079
|
||||
*
|
||||
* @param bytes The bytes to convert.
|
||||
* @return A {@link String} converted from the bytes of a hashable key used
|
||||
* to store a filename on the disk, to hex digits.
|
||||
*/
|
||||
private static String bytesToHexString(final byte[] bytes) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final byte b : bytes) {
|
||||
final String hex = Integer.toHexString(0xFF & b);
|
||||
if (hex.length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(hex);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private class CacheInputStreamPipe implements InputStreamPipe {
|
||||
|
||||
private final String mKey;
|
||||
@@ -372,7 +370,8 @@ public class SimpleDiskCache {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InputStream open() throws IOException {
|
||||
public @NonNull
|
||||
InputStream open() throws IOException {
|
||||
if (mLock == null) {
|
||||
throw new IllegalStateException("Please obtain it first");
|
||||
}
|
||||
@@ -431,7 +430,8 @@ public class SimpleDiskCache {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull OutputStream open() throws IOException {
|
||||
public @NonNull
|
||||
OutputStream open() throws IOException {
|
||||
if (mLock == null) {
|
||||
throw new IllegalStateException("Please obtain it first");
|
||||
}
|
||||
|
||||
@@ -45,155 +45,155 @@ import java.nio.charset.Charset;
|
||||
* The default charset is US_ASCII.
|
||||
*/
|
||||
class StrictLineReader implements Closeable {
|
||||
private static final byte CR = (byte) '\r';
|
||||
private static final byte LF = (byte) '\n';
|
||||
private static final byte CR = (byte) '\r';
|
||||
private static final byte LF = (byte) '\n';
|
||||
|
||||
private final InputStream in;
|
||||
private final Charset charset;
|
||||
private final InputStream in;
|
||||
private final Charset charset;
|
||||
|
||||
/*
|
||||
* Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
|
||||
* and the data in the range [pos, end) is buffered for reading. At end of input, if there is
|
||||
* an unterminated line, we set end == -1, otherwise end == pos. If the underlying
|
||||
* {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
|
||||
*/
|
||||
private byte[] buf;
|
||||
private int pos;
|
||||
private int end;
|
||||
/*
|
||||
* Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
|
||||
* and the data in the range [pos, end) is buffered for reading. At end of input, if there is
|
||||
* an unterminated line, we set end == -1, otherwise end == pos. If the underlying
|
||||
* {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
|
||||
*/
|
||||
private byte[] buf;
|
||||
private int pos;
|
||||
private int end;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LineReader} with the specified charset and the default capacity.
|
||||
*
|
||||
* @param in the {@code InputStream} to read data from.
|
||||
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
|
||||
* supported.
|
||||
* @throws NullPointerException if {@code in} or {@code charset} is null.
|
||||
* @throws IllegalArgumentException if the specified charset is not supported.
|
||||
*/
|
||||
public StrictLineReader(InputStream in, Charset charset) {
|
||||
this(in, 8192, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LineReader} with the specified capacity and charset.
|
||||
*
|
||||
* @param in the {@code InputStream} to read data from.
|
||||
* @param capacity the capacity of the buffer.
|
||||
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
|
||||
* supported.
|
||||
* @throws NullPointerException if {@code in} or {@code charset} is null.
|
||||
* @throws IllegalArgumentException if {@code capacity} is negative or zero
|
||||
* or the specified charset is not supported.
|
||||
*/
|
||||
public StrictLineReader(InputStream in, int capacity, Charset charset) {
|
||||
if (in == null || charset == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (capacity < 0) {
|
||||
throw new IllegalArgumentException("capacity <= 0");
|
||||
}
|
||||
if (!(charset.equals(Util.US_ASCII))) {
|
||||
throw new IllegalArgumentException("Unsupported encoding");
|
||||
/**
|
||||
* Constructs a new {@code LineReader} with the specified charset and the default capacity.
|
||||
*
|
||||
* @param in the {@code InputStream} to read data from.
|
||||
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
|
||||
* supported.
|
||||
* @throws NullPointerException if {@code in} or {@code charset} is null.
|
||||
* @throws IllegalArgumentException if the specified charset is not supported.
|
||||
*/
|
||||
public StrictLineReader(InputStream in, Charset charset) {
|
||||
this(in, 8192, charset);
|
||||
}
|
||||
|
||||
this.in = in;
|
||||
this.charset = charset;
|
||||
buf = new byte[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the reader by closing the underlying {@code InputStream} and
|
||||
* marking this reader as closed.
|
||||
*
|
||||
* @throws IOException for errors when closing the underlying {@code InputStream}.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
synchronized (in) {
|
||||
if (buf != null) {
|
||||
buf = null;
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
|
||||
* this end of line marker is not included in the result.
|
||||
*
|
||||
* @return the next line from the input.
|
||||
* @throws IOException for underlying {@code InputStream} errors.
|
||||
* @throws EOFException for the end of source stream.
|
||||
*/
|
||||
public String readLine() throws IOException {
|
||||
synchronized (in) {
|
||||
if (buf == null) {
|
||||
throw new IOException("LineReader is closed");
|
||||
}
|
||||
|
||||
// Read more data if we are at the end of the buffered data.
|
||||
// Though it's an error to read after an exception, we will let {@code fillBuf()}
|
||||
// throw again if that happens; thus we need to handle end == -1 as well as end == pos.
|
||||
if (pos >= end) {
|
||||
fillBuf();
|
||||
}
|
||||
// Try to find LF in the buffered data and return the line if successful.
|
||||
for (int i = pos; i != end; ++i) {
|
||||
if (buf[i] == LF) {
|
||||
int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
|
||||
String res = new String(buf, pos, lineEnd - pos, charset.name());
|
||||
pos = i + 1;
|
||||
return res;
|
||||
/**
|
||||
* Constructs a new {@code LineReader} with the specified capacity and charset.
|
||||
*
|
||||
* @param in the {@code InputStream} to read data from.
|
||||
* @param capacity the capacity of the buffer.
|
||||
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
|
||||
* supported.
|
||||
* @throws NullPointerException if {@code in} or {@code charset} is null.
|
||||
* @throws IllegalArgumentException if {@code capacity} is negative or zero
|
||||
* or the specified charset is not supported.
|
||||
*/
|
||||
public StrictLineReader(InputStream in, int capacity, Charset charset) {
|
||||
if (in == null || charset == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
}
|
||||
|
||||
// Let's anticipate up to 80 characters on top of those already read.
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
|
||||
try {
|
||||
return new String(buf, 0, length, charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e); // Since we control the charset this will never happen.
|
||||
}
|
||||
if (capacity < 0) {
|
||||
throw new IllegalArgumentException("capacity <= 0");
|
||||
}
|
||||
if (!(charset.equals(Util.US_ASCII))) {
|
||||
throw new IllegalArgumentException("Unsupported encoding");
|
||||
}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
out.write(buf, pos, end - pos);
|
||||
// Mark unterminated line in case fillBuf throws EOFException or IOException.
|
||||
end = -1;
|
||||
fillBuf();
|
||||
// Try to find LF in the buffered data and return the line if successful.
|
||||
for (int i = pos; i != end; ++i) {
|
||||
if (buf[i] == LF) {
|
||||
if (i != pos) {
|
||||
out.write(buf, pos, i - pos);
|
||||
this.in = in;
|
||||
this.charset = charset;
|
||||
buf = new byte[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the reader by closing the underlying {@code InputStream} and
|
||||
* marking this reader as closed.
|
||||
*
|
||||
* @throws IOException for errors when closing the underlying {@code InputStream}.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
synchronized (in) {
|
||||
if (buf != null) {
|
||||
buf = null;
|
||||
in.close();
|
||||
}
|
||||
pos = i + 1;
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasUnterminatedLine() {
|
||||
return end == -1;
|
||||
}
|
||||
/**
|
||||
* Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
|
||||
* this end of line marker is not included in the result.
|
||||
*
|
||||
* @return the next line from the input.
|
||||
* @throws IOException for underlying {@code InputStream} errors.
|
||||
* @throws EOFException for the end of source stream.
|
||||
*/
|
||||
public String readLine() throws IOException {
|
||||
synchronized (in) {
|
||||
if (buf == null) {
|
||||
throw new IOException("LineReader is closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads new input data into the buffer. Call only with pos == end or end == -1,
|
||||
* depending on the desired outcome if the function throws.
|
||||
*/
|
||||
private void fillBuf() throws IOException {
|
||||
int result = in.read(buf, 0, buf.length);
|
||||
if (result == -1) {
|
||||
throw new EOFException();
|
||||
// Read more data if we are at the end of the buffered data.
|
||||
// Though it's an error to read after an exception, we will let {@code fillBuf()}
|
||||
// throw again if that happens; thus we need to handle end == -1 as well as end == pos.
|
||||
if (pos >= end) {
|
||||
fillBuf();
|
||||
}
|
||||
// Try to find LF in the buffered data and return the line if successful.
|
||||
for (int i = pos; i != end; ++i) {
|
||||
if (buf[i] == LF) {
|
||||
int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
|
||||
String res = new String(buf, pos, lineEnd - pos, charset.name());
|
||||
pos = i + 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// Let's anticipate up to 80 characters on top of those already read.
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
|
||||
try {
|
||||
return new String(buf, 0, length, charset.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e); // Since we control the charset this will never happen.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
out.write(buf, pos, end - pos);
|
||||
// Mark unterminated line in case fillBuf throws EOFException or IOException.
|
||||
end = -1;
|
||||
fillBuf();
|
||||
// Try to find LF in the buffered data and return the line if successful.
|
||||
for (int i = pos; i != end; ++i) {
|
||||
if (buf[i] == LF) {
|
||||
if (i != pos) {
|
||||
out.write(buf, pos, i - pos);
|
||||
}
|
||||
pos = i + 1;
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasUnterminatedLine() {
|
||||
return end == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads new input data into the buffer. Call only with pos == end or end == -1,
|
||||
* depending on the desired outcome if the function throws.
|
||||
*/
|
||||
private void fillBuf() throws IOException {
|
||||
int result = in.read(buf, 0, buf.length);
|
||||
if (result == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
pos = 0;
|
||||
end = result;
|
||||
}
|
||||
pos = 0;
|
||||
end = result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,76 +26,77 @@ import java.io.StringWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/** Junk drawer of utility methods. */
|
||||
/**
|
||||
* Junk drawer of utility methods.
|
||||
*/
|
||||
final class Util {
|
||||
static final Charset US_ASCII = StandardCharsets.US_ASCII;
|
||||
static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||
static final Charset US_ASCII = StandardCharsets.US_ASCII;
|
||||
static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||
private static final int EOF = -1;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
|
||||
|
||||
private Util() {
|
||||
}
|
||||
|
||||
static String readFully(Reader reader) throws IOException {
|
||||
try (reader) {
|
||||
StringWriter writer = new StringWriter();
|
||||
char[] buffer = new char[1024];
|
||||
int count;
|
||||
while ((count = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, count);
|
||||
}
|
||||
return writer.toString();
|
||||
private Util() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the contents of {@code dir}. Throws an IOException if any file
|
||||
* could not be deleted, or if {@code dir} is not a readable directory.
|
||||
*/
|
||||
static void deleteContents(File dir) throws IOException {
|
||||
File[] files = dir.listFiles();
|
||||
if (files == null) {
|
||||
throw new IOException("not a readable directory: " + dir);
|
||||
static String readFully(Reader reader) throws IOException {
|
||||
try (reader) {
|
||||
StringWriter writer = new StringWriter();
|
||||
char[] buffer = new char[1024];
|
||||
int count;
|
||||
while ((count = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, count);
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteContents(file);
|
||||
}
|
||||
if (!file.delete()) {
|
||||
throw new IOException("failed to delete file: " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void closeQuietly(/*Auto*/Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (RuntimeException rethrown) {
|
||||
throw rethrown;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
/**
|
||||
* Deletes the contents of {@code dir}. Throws an IOException if any file
|
||||
* could not be deleted, or if {@code dir} is not a readable directory.
|
||||
*/
|
||||
static void deleteContents(File dir) throws IOException {
|
||||
File[] files = dir.listFiles();
|
||||
if (files == null) {
|
||||
throw new IOException("not a readable directory: " + dir);
|
||||
}
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteContents(file);
|
||||
}
|
||||
if (!file.delete()) {
|
||||
throw new IOException("failed to delete file: " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int EOF = -1;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
|
||||
static void closeQuietly(/*Auto*/Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (RuntimeException rethrown) {
|
||||
throw rethrown;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bytes from an <code>InputStream</code> to an
|
||||
* <code>OutputStream</code>.
|
||||
*
|
||||
* @param input the InputStream
|
||||
* @param output the OutputStream
|
||||
* @return the number of bytes copied
|
||||
*/
|
||||
public static long copy(InputStream input, OutputStream output)
|
||||
throws IOException {
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
long count = 0;
|
||||
int n;
|
||||
while (EOF != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
count += n;
|
||||
/**
|
||||
* Copy bytes from an <code>InputStream</code> to an
|
||||
* <code>OutputStream</code>.
|
||||
*
|
||||
* @param input the InputStream
|
||||
* @param output the OutputStream
|
||||
* @return the number of bytes copied
|
||||
*/
|
||||
public static long copy(InputStream input, OutputStream output)
|
||||
throws IOException {
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
long count = 0;
|
||||
int n;
|
||||
while (EOF != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
count += n;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -283,16 +283,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
outState.putInt(KEY_PAGE, mPage);
|
||||
outState.putInt(KEY_CURRENT_INDEX, mCurrentIndex);
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(@NonNull Context newBase) {
|
||||
@@ -305,7 +296,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
break;
|
||||
}
|
||||
super.attachBaseContext(newBase);
|
||||
}
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
|
||||
@Override
|
||||
public boolean respectDefaultNightMode() {
|
||||
|
||||
@@ -68,7 +68,6 @@ import com.hippo.ehviewer.client.data.FavListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.parser.FavoritesParser;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.ehviewer.ui.EhActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.ui.annotation.DrawerLifeCircle;
|
||||
import com.hippo.ehviewer.ui.annotation.ViewLifeCircle;
|
||||
|
||||
@@ -60,9 +60,6 @@ import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.transition.TransitionInflater;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator;
|
||||
@@ -103,7 +100,6 @@ import com.hippo.ehviewer.ui.annotation.WholeLifeCircle;
|
||||
import com.hippo.ehviewer.widget.GalleryRatingBar;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.scene.TransitionHelper;
|
||||
import com.hippo.text.Html;
|
||||
import com.hippo.text.URLImageGetter;
|
||||
import com.hippo.util.AppHelper;
|
||||
|
||||
@@ -96,7 +96,6 @@ import com.hippo.ehviewer.dao.DownloadLabel;
|
||||
import com.hippo.ehviewer.dao.QuickSearch;
|
||||
import com.hippo.ehviewer.download.DownloadManager;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.ehviewer.ui.EhActivity;
|
||||
import com.hippo.ehviewer.ui.GalleryActivity;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter;
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.view.MotionEvent;
|
||||
class DownUpDetector {
|
||||
private final DownUpListener mListener;
|
||||
private boolean mStillDown;
|
||||
|
||||
public DownUpDetector(DownUpListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ public abstract class GalleryProvider {
|
||||
private float mPercent;
|
||||
private ImageWrapper mImage;
|
||||
private String mError;
|
||||
|
||||
public NotifyTask(Listener listener, ConcurrentPool<NotifyTask> pool) {
|
||||
mListener = listener;
|
||||
mPool = pool;
|
||||
|
||||
@@ -137,6 +137,7 @@ public final class GalleryView extends GLView implements GestureRecognizer.Liste
|
||||
private int mScaleMode = ImageView.SCALE_FIT;
|
||||
private int mStartPosition = ImageView.START_POSITION_TOP_LEFT;
|
||||
private int mIndex;
|
||||
|
||||
private GalleryView(Builder build) {
|
||||
mContext = build.mContext;
|
||||
mAdapter = build.mAdapter;
|
||||
|
||||
@@ -33,6 +33,7 @@ class GestureRecognizer {
|
||||
private final ScaleGestureDetector mScaleDetector;
|
||||
private final DownUpDetector mDownUpDetector;
|
||||
private final Listener mListener;
|
||||
|
||||
public GestureRecognizer(Context context, Listener listener) {
|
||||
mListener = listener;
|
||||
MyGestureListener gestureListener = new MyGestureListener();
|
||||
|
||||
@@ -216,6 +216,7 @@ public class GLES20Canvas implements GLCanvas {
|
||||
private int mCountTextureRect = 0;
|
||||
private int mCountFillRect = 0;
|
||||
private int mCountDrawLine = 0;
|
||||
|
||||
public GLES20Canvas() {
|
||||
Matrix.setIdentityM(mTempTextureMatrix, 0);
|
||||
Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
|
||||
|
||||
@@ -41,6 +41,7 @@ public final class GLEdgeView extends GLView {
|
||||
private static final int RIGHT_M = RIGHT * 16;
|
||||
private final GLEdgeEffect[] mEffect = new GLEdgeEffect[4];
|
||||
private final float[] mMatrix = new float[4 * 16];
|
||||
|
||||
public GLEdgeView(int color) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mEffect[i] = new GLEdgeEffect(color);
|
||||
|
||||
@@ -511,17 +511,17 @@ public abstract class StageActivity extends EhActivity {
|
||||
|
||||
FragmentTransaction transaction = fragmentManager.beginTransaction();
|
||||
if (next != null) {
|
||||
// Clear shared item
|
||||
scene.setSharedElementEnterTransition(null);
|
||||
scene.setSharedElementReturnTransition(null);
|
||||
scene.setEnterTransition(null);
|
||||
scene.setExitTransition(null);
|
||||
next.setSharedElementEnterTransition(null);
|
||||
next.setSharedElementReturnTransition(null);
|
||||
next.setEnterTransition(null);
|
||||
next.setExitTransition(null);
|
||||
// Do not show animate if it is not the first fragment
|
||||
transaction.setCustomAnimations(R.anim.scene_close_enter, R.anim.scene_close_exit);
|
||||
// Clear shared item
|
||||
scene.setSharedElementEnterTransition(null);
|
||||
scene.setSharedElementReturnTransition(null);
|
||||
scene.setEnterTransition(null);
|
||||
scene.setExitTransition(null);
|
||||
next.setSharedElementEnterTransition(null);
|
||||
next.setSharedElementReturnTransition(null);
|
||||
next.setEnterTransition(null);
|
||||
next.setExitTransition(null);
|
||||
// Do not show animate if it is not the first fragment
|
||||
transaction.setCustomAnimations(R.anim.scene_close_enter, R.anim.scene_close_exit);
|
||||
// Attach fragment
|
||||
transaction.attach(next);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,13 @@ public class BatteryView extends AppCompatTextView {
|
||||
|
||||
mDrawable.setColor(mColor);
|
||||
mDrawable.setWarningColor(mWarningColor);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mDrawable = new BatteryDrawable();
|
||||
int height = (int) getTextSize();
|
||||
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
|
||||
setCompoundDrawables(mDrawable, null, null, null);
|
||||
} private final Runnable mCharger = new Runnable() {
|
||||
|
||||
private int level = 0;
|
||||
@@ -81,13 +88,6 @@ public class BatteryView extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
private void init() {
|
||||
mDrawable = new BatteryDrawable();
|
||||
int height = (int) getTextSize();
|
||||
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
|
||||
setCompoundDrawables(mDrawable, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(int color) {
|
||||
if (mCurrentColor == color) {
|
||||
@@ -137,7 +137,13 @@ public class BatteryView extends AppCompatTextView {
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
|
||||
} private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
}
|
||||
|
||||
private void unregisterReceiver() {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
@@ -168,12 +174,6 @@ public class BatteryView extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
private void unregisterReceiver() {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -83,6 +83,12 @@ public class TextClock extends AppCompatTextView {
|
||||
mTimeZone = TimeZone.getDefault().getID();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
createTime(mTimeZone);
|
||||
// Wait until onAttachedToWindow() to handle the ticker
|
||||
chooseFormat(false);
|
||||
} private final Runnable mTicker = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -95,12 +101,6 @@ public class TextClock extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
private void init() {
|
||||
createTime(mTimeZone);
|
||||
// Wait until onAttachedToWindow() to handle the ticker
|
||||
chooseFormat(false);
|
||||
}
|
||||
|
||||
private void createTime(String timeZone) {
|
||||
if (timeZone != null) {
|
||||
mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
|
||||
@@ -122,6 +122,17 @@ public class TextClock extends AppCompatTextView {
|
||||
|
||||
public CharSequence getFormat24Hour() {
|
||||
return mFormat24;
|
||||
}
|
||||
|
||||
public void setFormat24Hour(CharSequence format) {
|
||||
mFormat24 = format;
|
||||
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
public boolean is24HourModeEnabled() {
|
||||
return DateFormat.is24HourFormat(getContext());
|
||||
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
@@ -136,17 +147,6 @@ public class TextClock extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
public void setFormat24Hour(CharSequence format) {
|
||||
mFormat24 = format;
|
||||
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
public boolean is24HourModeEnabled() {
|
||||
return DateFormat.is24HourFormat(getContext());
|
||||
}
|
||||
|
||||
public String getTimeZone() {
|
||||
return mTimeZone;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public final class AnimationUtils {
|
||||
public static final Interpolator FAST_SLOW_INTERPOLATOR = new LinearOutSlowInInterpolator();
|
||||
public static final Interpolator SLOW_FAST_INTERPOLATOR = new FastOutLinearInInterpolator();
|
||||
public static final Interpolator SLOW_FAST_SLOW_INTERPOLATOR = new FastOutSlowInInterpolator();
|
||||
|
||||
private AnimationUtils() {
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public final class MathUtils {
|
||||
private static final Random sRandom = new Random();
|
||||
private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
|
||||
private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
|
||||
|
||||
private MathUtils() {
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.annotation.AttrRes;
|
||||
public final class ResourcesUtils {
|
||||
private static final Object mAccessLock = new Object();
|
||||
private static TypedValue mTmpValue = new TypedValue();
|
||||
|
||||
private ResourcesUtils() {
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,8 @@ public class InfiniteThreadExecutor implements Executor {
|
||||
private final ThreadFactory mThreadFactory;
|
||||
|
||||
private final AtomicInteger mThreadCount = new AtomicInteger();
|
||||
private int mEmptyThreadCount;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private int mEmptyThreadCount;
|
||||
|
||||
public InfiniteThreadExecutor(long keepAliveMillis, Queue<Runnable> workQueue, ThreadFactory threadFactory) {
|
||||
mKeepAliveMillis = keepAliveMillis;
|
||||
@@ -65,7 +64,7 @@ public class InfiniteThreadExecutor implements Executor {
|
||||
mThreadCount.incrementAndGet();
|
||||
|
||||
boolean hasWait = false;
|
||||
for (;;) {
|
||||
for (; ; ) {
|
||||
Runnable command;
|
||||
synchronized (mLock) {
|
||||
command = mWorkQueue.poll();
|
||||
|
||||
@@ -26,18 +26,16 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class SerialThreadExecutor implements Executor, Runnable {
|
||||
|
||||
private final Lock mThreadLock = new ReentrantLock();
|
||||
private final Object mWaitLock = new Object();
|
||||
private long mKeepAliveMillis;
|
||||
private Queue<Runnable> mWorkQueue;
|
||||
private ThreadFactory mThreadFactory;
|
||||
|
||||
// The worker
|
||||
private Thread mThread;
|
||||
|
||||
private final Lock mThreadLock = new ReentrantLock();
|
||||
private final Object mWaitLock = new Object();
|
||||
|
||||
public SerialThreadExecutor(long keepAliveMillis,
|
||||
Queue<Runnable> workQueue, ThreadFactory threadFactory) {
|
||||
Queue<Runnable> workQueue, ThreadFactory threadFactory) {
|
||||
mKeepAliveMillis = keepAliveMillis;
|
||||
mWorkQueue = workQueue;
|
||||
mThreadFactory = threadFactory;
|
||||
@@ -67,7 +65,7 @@ public class SerialThreadExecutor implements Executor, Runnable {
|
||||
// It tell whether has waited
|
||||
boolean hasWaited = false;
|
||||
|
||||
for (;;) {
|
||||
for (; ; ) {
|
||||
mThreadLock.lock();
|
||||
Runnable runnable = mWorkQueue.poll();
|
||||
if (runnable == null) {
|
||||
|
||||
Reference in new issue
Block a user