Discache的抽象实现。
源码:
/**
* Base disk cache.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @see FileNameGenerator
* @since 1.0.0
*/
public abstract class BaseDiskCache implements DiskCache {
/** {@value */
public static final int DEFAULT_BUFFER_SIZE = 32 * 1024; // 32 Kb,读文件的时候的额buffer大小
/** {@value */
public static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG;//文件解析方法
/** {@value */
public static final int DEFAULT_COMPRESS_QUALITY = 100;//文件压缩比例
private static final String ERROR_ARG_NULL = " argument must be not null";
private static final String TEMP_IMAGE_POSTFIX = ".tmp";//临时文件的扩展名
protected final File cacheDir;//缓存地址
protected final File reserveCacheDir;//备用地址
protected final FileNameGenerator fileNameGenerator;//文件名生成器
protected int bufferSize = DEFAULT_BUFFER_SIZE;
protected Bitmap.CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT;
protected int compressQuality = DEFAULT_COMPRESS_QUALITY;
/** @param cacheDir Directory for file caching */
public BaseDiskCache(File cacheDir) {
this(cacheDir, null);
}
/**
* @param cacheDir Directory for file caching
* @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available.
*/
public BaseDiskCache(File cacheDir, File reserveCacheDir) {
this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator());
}
/**
* @param cacheDir Directory for file caching
* @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available.
* @param fileNameGenerator {@linkplain com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator
* Name generator} for cached files
*/
public BaseDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {
if (cacheDir == null) {
throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL);
}
if (fileNameGenerator == null) {
throw new IllegalArgumentException("fileNameGenerator" + ERROR_ARG_NULL);
}
this.cacheDir = cacheDir;
this.reserveCacheDir = reserveCacheDir;
this.fileNameGenerator = fileNameGenerator;
}
@Override
public File getDirectory() {
return cacheDir;
}
@Override
public File get(String imageUri) {
return getFile(imageUri);
}
@Override
public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {//将流中数据存储到文件中,先把内容写到临时文件中,然后再重命名为目标文件
File imageFile = getFile(imageUri);
File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
boolean loaded = false;
try {
OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
try {
loaded = IoUtils.copyStream(imageStream, os, listener, bufferSize);
} finally {
IoUtils.closeSilently(os);
}
} finally {
if (loaded && !tmpFile.renameTo(imageFile)) {
loaded = false;
}
if (!loaded) {
tmpFile.delete();
}
}
return loaded;
}
@Override
public boolean save(String imageUri, Bitmap bitmap) throws IOException {//保存图片,也是采用先写到临时文件在重命名的策略,这个可以借鉴
File imageFile = getFile(imageUri);
File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
boolean savedSuccessfully = false;
try {
savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os);
} finally {
IoUtils.closeSilently(os);
if (savedSuccessfully && !tmpFile.renameTo(imageFile)) {
savedSuccessfully = false;
}
if (!savedSuccessfully) {
tmpFile.delete();
}
}
bitmap.recycle();
return savedSuccessfully;
}
@Override
public boolean remove(String imageUri) {
return getFile(imageUri).delete();
}
@Override
public void close() {
// Nothing to do
}
@Override
public void clear() {
File[] files = cacheDir.listFiles();
if (files != null) {
for (File f : files) {
f.delete();
}
}
}
/** Returns file object (not null) for incoming image URI. File object can reference to non-existing file. */
protected File getFile(String imageUri) {
String fileName = fileNameGenerator.generate(imageUri);
File dir = cacheDir;
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
if (reserveCacheDir != null && (reserveCacheDir.exists() || reserveCacheDir.mkdirs())) {
dir = reserveCacheDir;
}
}
return new File(dir, fileName);
}
public void setBufferSize(int bufferSize) {
this.bufferSize = bufferSize;
}
public void setCompressFormat(Bitmap.CompressFormat compressFormat) {
this.compressFormat = compressFormat;
}
public void setCompressQuality(int compressQuality) {
this.compressQuality = compressQuality;
}
}