Translations: 简体中文
In order to avoid repeatedly downloading pictures from the network and improve the loading speed of pictures, Sketch has introduced download cache. The download cache function will first store the pictures on disk for a long time, then read them from disk, and skip the download process next time you read them directly from disk.
HttpUriFetcher is responsible for the core logic, and DiskCache is responsible for the storage management.
The default implementation of DiskCache is LruDiskCache:
- The default maximum capacity is 300 MB
- Clear old cache based on least used principle
In order to adapt to the differences between different platforms, the locations of cache directories are also different on different platforms.
The default download cache directory on Android is obtained in the following order:
/sdcard/Android/data/[APP_PACKAGE_NAME]/cache/sketch4/download/data/data/[APP_PACKAGE_NAME]/cache/sketch4/download
Tip
In order to be compatible with multiple processes, when using Sketch in a non-main process, the process name will be added after the cache directory name, such as "download:push"
The default download cache directory on iOS is:
val appCacheDirectory =
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true).first() as String
val downloadCacheDir = "$appCacheDirectory/sketch4/download"The default download cache directory on jvm platforms is:
val appId = getJarPath(PlatformContext::class.java)
?.substringBefore("${File.separator}build${File.separator}") // Debug
?.substringBefore("${File.separator}app${File.separator}") // Release
?.md5()
?.let { "SketchImageLoader${File.separator}${it}" }
?: return null
// macOS
"/Users/[user]/Library/Caches/${appId}/sketch4/download"
// Windows
"C:\\Users\\[user]\\AppData\\Local\\${appId}\\Cache\\sketch4\\download"
// Linux
"/home/[user]/.cache/${appId}/sketch4/download"val appId = NSBundle.mainBundle.bundleIdentifier?.takeIf { it.isNotEmpty() }
?: NSBundle.mainBundle.bundlePath.takeIf { it.isNotEmpty() }
?.substringBefore("/build/")
?.md5()
?.let { "SketchImageLoader/${it}" }
?: return null
val downloadCacheDir = "/Users/[user]/Library/Caches/${appId}/sketch4/download"The web platform does not yet support download caching
Warning
Since Sketch on JVM and macOS platforms defaults to using the program's runtime path to build the download cache directory, any change to the runtime path will cause the download cache to become invalid. Therefore, please configure a stable download cache directory when initializing Sketch.
When initializing Sketch, you can customize the download cache implementation or various configurations using the downloadCache() or downloadCacheOptions() methods of Sketch.Builder, as follows:
// Use the default LruDiskCache implementation and configure its parameters
Sketch.Builder(context).apply {
downloadCacheOptions(
DiskCache.Options(
// Just choose one of directory and appCacheDirectory
directory = "/tmp/myapp/sketch/download".toPath(),
// or
appCacheDirectory = "/tmp/myapp".toPath(),
// or. AppDirs is available only on the JVM platform.
appCacheDirectory = AppDirs.getCacheDir("MyAppName").toOkioPath(),
// 100 MB
maxSize = 1024 * 1024 * 100,
// The app's management version number for the download cache.
// If you want to clear the old download cache, upgrade this version number.
appVersion = 1,
)
)
}.build()
// Use your own DiskCache implementation
class MyDiskCache : DiskCache {
// ...
}
Sketch.Builder(context).apply {
downloadCache(MyDiskCache())
}.build()The download cache policy is used to control how to use the download cache. The default configuration is CachePolicy.ENABLED, which you can configure via the downloadCachePolicy property of ImageRequest or ImageOptions:
ImageRequest(context, "https://example.com/image.jpg") {
// Disable
downloadCachePolicy(CachePolicy.DISABLED)
// Read only
downloadCachePolicy(CachePolicy.READ_ONLY)
// Write Only
downloadCachePolicy(CachePolicy.WRITE_ONLY)
}By default, Sketch will automatically generate a download cache key based on the requested configuration, but you can also customize the download cache key with the following properties:
ImageRequest(context, "https://example.com/image.jpg") {
// Use custom download cache key
downloadCacheKey("https://example.com/image.jpg?width=100&height=100")
// Modify the automatically generated download cache key
downloadCacheKeyMapper(CacheKeyMapper { "${it}&width=100&height=100" })
}
ImageOptions {
// Use custom download cache key
downloadCacheKey("https://example.com/image.jpg?width=100&height=100")
// Modify the automatically generated download cache key
downloadCacheKeyMapper(CacheKeyMapper { "${it}&width=100&height=100" })
}You can also get the final download cache key through the following methods:
// The download cache key can be obtained through RequestContext in the customized Interceptor,
// Transformation, Fetcher, and Decoder components.
val requestContext: RequestContext = ...
requestContext.downloadCacheKey
// Get the download cache key from ImageResult
val imageSuccess = sketch.execute(request) as ImageResult.Success
imageSuccess.downloadCacheKeyYou can obtain the download cache instance through the sketch.downloadCache property to access the
download cache, but be careful to obtain the lock first before accessing, so as to avoid problems
under multi-threading, as follows:
scope.launch {
val downloadCache = sketch.downloadCache
val downloadCacheKey = imageRequest.downoadCacheKey
downloadCache.withLock(downloadCacheKey) {
// get
openSnapshot(downloadCacheKey)?.use { snapshot ->
val dataPath: Path = snapshot.data
val metadataPath: Path = snapshot.metadata
val dataContent = fileSystem.source(dataPath).buffer().use {
it.readUtf8()
}
val metadataContent = fileSystem.source(metadataPath).buffer().use {
it.readUtf8()
}
}
// edit
val editor: DiskCache.Editor? = openEditor(downloadCacheKey)
if (editor != null) {
try {
val dataPath: Path = editor.data
val metadataPath: Path = editor.metadata
fileSystem.sink(dataPath).buffer().use {
it.writeUtf8("data")
}
fileSystem.sink(metadataPath).buffer().use {
it.writeUtf8("metadata")
}
editor.commit()
} catch (e: Exception) {
editor.abort()
}
}
// remove
val cleared: Boolean = remove(downloadCacheKey)
}
// Clear all
downloadCache.clear()
}Caution
- openSnapshot and openEditor with the same key conflict with each other. For example, openSnapshot is not closed before openEditor is closed. Always returns null and vice versa
- So it must be executed inside withLock, otherwise unexpected events may occur.
For more available methods, please refer to DiskCache
The download cache is cleared under the following circumstances: