ImageLoader local cache developed by Android

  • 2020-12-21 18:11:06
  • OfStack

ImageLoader is an open source image cache library, which provides a powerful image cache mechanism, which is used by many developers. Today, I would like to introduce ImageLoader local cache developed by Android. The specific contents are as follows:

There are two ways to change the name of a file when it is cached locally, each of which corresponds to an Java class

1) HashCodeFileNameGenerator, which is responsible for getting the hashcode of the file name and then converting it into a string.

2) Md5FileNameGenerator, which saves the name of the source file after encryption with md5.

Both classes inherit from the FileNameGenerator interface

A factory method, createFileNameGenerator, is provided in the DefaultConfigurationFactory class, which returns the default FileNameGenerator object: HashCodeFileNameGenerator.


public static FileNameGenerator createFileNameGenerator() { 
return new HashCodeFileNameGenerator(); 
}

implementation

First you define the DiscCacheAware interface, which provides the following methods


File getFileDectory()  Returns the root directory of the disk cache 
File get(String imageUri)  According to the uri Gets the image from the cache 
boolean save(String imageUri,InputStream iamgeStream,IoUtils.CopyListener listener)  Save the image in the disk cache 
boolean save(String imageUri,Bitmap bitmap)  save bitmap Object to disk cache 
boolean remove(imageUri)  According to the imageUri Delete the file 
void close()  Close the disk cache and free up resources 
void clear()  Clear disk cache 

It then defines another non-method interface, DiskCache, which simply inherits the DiscCacheAware interface.

BaseDiscCache implements DiskCache, which is an abstract class that defines the following properties of the disk buffer:

1) The default cache size is 32k

2) The default compressed image format is PNG (as the first parameter of the compress method of Bitmap)

3) The quality of the image displayed after the default compression is 100, that is, the compression rate is 0, and no compression (as the second parameter of compress)

Provides set methods to modify the compressed image format and compression rate, as well as to modify the cache size. The class also encapsulates the following three properties


protected final File cacheDir;// The storage of cache files Directory
protected final File reserveCacheDir;// Backup cached Diectory when cacheDir It's used when it doesn't exist reserveCahceDir Backup cache 
protected final FileNameGenerator fileNameGenerator;// File name generator 

The constructor


public BaseDiscCache(File cacheDir) {
this(cacheDir, null);
}
public BaseDiscCache(File cacheDir, File reserveCacheDir) {
this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator());
}
public BaseDiscCache(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;
}

1) The constructor with only 1 parameter initializes cacheDir, does not use the backup cache, and generates the file name of the target file as HashCodeFileNameGenerator.

2) The constructor of the two parameters, in addition to cacheDir and HashCodefileNameGenerator, can also initialize the backup cache

3) The constructor with 3 parameters requires that cacheDir must be initialized and filenNameGenerator must be initialized or the exception will be reported

get(String imageUri)


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); 
}

save(String imageUri, Bitmap bitmap)


public boolean save(String imageUri, Bitmap bitmap) throws IOException { 
// To obtain imageUri the File Object that encapsulates the cache path and the name of the image after it is saved  
File imageFile = getFile(imageUri); 
// Gets temporarily saved file tmpFile object  
File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX); 
OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize); 
boolean savedSuccessfully = false; 
try { 
// call compress the bitMap Compressed into tempFile In the  
savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os); 
} finally { 
IoUtils.closeSilently(os); 
// If saved successfully and tempFile File was not successfully moved to imageFile If so, delete it temFile 
if (savedSuccessfully && !tmpFile.renameTo(imageFile)) { 
savedSuccessfully = false; 
} 
if (!savedSuccessfully) { 
tmpFile.delete(); 
} 
} 
// right bitmap Garbage collection  
bitmap.recycle(); 
return savedSuccessfully; 
}

BaseDiscCache has two extension classes, one is UnlimitedDiscCache, which does not limit cache size, and LimitedAgeDiscCache, which limits cache time. UnlimitedDiscCache is very simple. It simply inherits BaseDiscCache and does not extend BaseDiscCache at all.

The LimitedAgeDiscCache class removes files from the cache that have been loaded for longer than the specified time: files are removed from the cache when the following conditions are met: current system time - the last modification time of the file > maxFileAge

LimitedAgeDiscCache

This class provides two properties:

1. maxFileAge (long) sets the maximum time for loading timeout. The change time is initialized in the constructor, and 1 cannot be changed after initialization (the maximum surviving time of the file is set, and the file will be deleted if the value is exceeded).

2. loadingDates (Map < File,long > ), the attribute is a map type of object, key saved to cache the image files, and value saved is call save method is a system of the current time, specific to the loadingDates populate the data are implemented in the following rememberUsage method, this method two save method call in the class, first call the superclass save method, and then this method is called


private void rememberUsage(String imageUri) { 
File file = getFile(imageUri); 
long currentTime = System.currentTimeMillis(); 
file.setLastModified(currentTime); 
loadingDates.put(file, currentTime); 
}

get(String imageUri), which overwrites the BaseDiscDache method, gets the latest update time of the image represented by imageUri from loadingDates, and then makes a difference between the current time and loadingDate. If the difference is greater than maxFileAge, which means that the maximum loading time has been checked, it deletes the file represented by the imageUri, and takes the data from loadingDates. Of course, if THERE is no imageUri in map, there will be no timeout issue. At this point, image is put into map. The implementation is as follows


@Override 
public File get(String imageUri) { 
File file = super.get(imageUri); 
if (file != null && file.exists()) { 
boolean cached; 
Long loadingDate = loadingDates.get(file); 
if (loadingDate == null) { 
cached = false; 
loadingDate = file.lastModified(); 
} else { 
cached = true; 
} 
if (System.currentTimeMillis() - loadingDate > maxFileAge) { 
file.delete(); 
loadingDates.remove(file); 
} else if (!cached) { 
loadingDates.put(file, loadingDate); 
} 
} 
return file; 
}


Related articles: