Download Cache

January 13, 2026 · View on GitHub

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

Cache Directory

In order to adapt to the differences between different platforms, the locations of cache directories are also different on different platforms.

Android

The default download cache directory on Android is obtained in the following order:

  1. /sdcard/Android/data/[APP_PACKAGE_NAME]/cache/sketch4/download
  2. /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"

iOS

The default download cache directory on iOS is:

val appCacheDirectory =
    NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true).first() as String
val downloadCacheDir = "$appCacheDirectory/sketch4/download"

Desktop

The default download cache directory on desktop platforms is:

val appName = (getComposeResourcesPath() ?: getJarPath(Sketch::class.java)).md5()

// macOS
"/Users/[user]/Library/Caches/SketchImageLoader/${appName}/sketch4/download"

// Windows
"C:\\Users\\[user]\\AppData\\Local\\SketchImageLoader\\${appName}\\sketch4/download\\Cache"

// Linux
"/home/[user]/.cache/SketchImageLoader/${appName}/sketch4/download"

Web

The web platform does not yet support download caching

Customize

You can pass Sketch.Builder's downloadCache() or downloadCacheOptions() when initializing Sketch Method to customize the implementation or configuration of download cache, 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",
            // Just choose one of directory and appCacheDirectory
            appCacheDirectory = "/tmp/myapp",
            // 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()

Cache Policy

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

Cache key

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.downloadCacheKey

Read and write cache

You 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

  1. 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
  2. So it must be executed inside withLock, otherwise unexpected events may occur.

For more available methods, please refer to DiskCache

Clear cache

The download cache is cleared under the following circumstances:

  1. Actively call the remove() and clear()` methods of DiskCache
  2. Actively call the abort() method of DiskCache.Editor
  3. Automatically clear older caches when maximum capacity is reached