Skip to content

Latest commit

 

History

History
252 lines (193 loc) · 8.39 KB

result_cache.md

File metadata and controls

252 lines (193 loc) · 8.39 KB

Result Cache

Translations: 简体中文

In order to avoid repeated conversion of pictures and improve the loading speed of pictures Sketch, the result cache function will store the converted pictures on disk for a long time, and skip the conversion process next time you read them directly from disk.

The result caching function is managed by ResultCacheInterceptor, and DiskCache is managed by the storage management.

The default implementation of DiskCache is LruDiskCache:

  • Default maximum capacity is 200 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 result cache directories on Android are obtained in the following order:

  1. /sdcard/Android/data/[APP_PACKAGE_NAME]/cache/sketch4/result
  2. /data/data/[APP_PACKAGE_NAME]/cache/sketch4/result

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 "result:push"

iOS

The default results cache directory on iOS is:

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

jvm

The default results 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/result"

// Windows
"C:\\Users\\[user]\\AppData\\Local\\${appId}\\Cache\\sketch4\\result"

// Linux
"/home/[user]/.cache/${appId}/sketch4/result"

macOS

val appId = NSBundle.mainBundle.bundleIdentifier?.takeIf { it.isNotEmpty() }
     ?: NSBundle.mainBundle.bundlePath.takeIf { it.isNotEmpty() }
          ?.substringBefore("/build/")
          ?.md5()
          ?.let { "SketchImageLoader/${it}" }
     ?: return null
val resultCacheDir = "/Users/[user]/Library/Caches/${appId}/sketch4/result"

Web

The web platform does not yet support result caching

Customize

Warning

Since Sketch on JVM and macOS platforms defaults to using the program's runtime path to build the result cache directory, any change to the runtime path will cause the result cache to become invalid. Therefore, please configure a stable result cache directory when initializing Sketch.

When initializing Sketch, you can customize the implementation or various configurations of the result cache using the resultCache() or resultCacheOptions() methods of Sketch.Builder, as follows:

// Use the default LruDiskCache implementation and configure its parameters
Sketch.Builder(context).apply {
    resultCacheOptions(
        DiskCache.Options(
            // Just choose one of directory and appCacheDirectory
             directory = "/tmp/myapp/sketch/result".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 result cache. 
            // If you want to clear the old result cache, upgrade this version number.
            appVersion = 1,
        )
    )
}.build()

// Use your own DiskCache implementation
class MyDiskCache : DiskCache {
    // ...
}
Sketch.Builder(context).apply {
    resultCache(MyDiskCache())
}.build()

Cache Policy

The result caching policy is used to control how to use the result caching. The default configuration is CachePolicy.ENABLED, which you can configure via the resultCachePolicy attribute of ImageRequest or ImageOptions:

ImageRequest(context, "https://example.com/image.jpg") {
    // Disable
    resultCachePolicy(CachePolicy.DISABLED)
    // Read only
    resultCachePolicy(CachePolicy.READ_ONLY)
    // Write Only
    resultCachePolicy(CachePolicy.WRITE_ONLY)
}

Cache key

By default, Sketch will automatically generate a result cache key based on the requested configuration, but you can also customize the result cache key with the following properties:

ImageRequest(context, "https://example.com/image.jpg") {
    // Use custom result cache key
    resultCacheKey("https://example.com/image.jpg?width=100&height=100")

    // Modify the automatically generated result cache key
    resultCacheKeyMapper(CacheKeyMapper { "${it}&width=100&height=100" })
}

ImageOptions {
    // Use custom result cache key
    resultCacheKey("https://example.com/image.jpg?width=100&height=100")

    // Modify the automatically generated result cache key
    resultCacheKeyMapper(CacheKeyMapper { "${it}&width=100&height=100" })
}

You can also get the final result cache key through the following methods:

// The result cache key can be obtained through RequestContext in the customized Interceptor, 
// Transformation, Fetcher, and Decoder components.
val requestContext: RequestContext = ...
requestContext.resultCacheKey

// Get the result cache key from ImageResult
val imageSuccess = sketch.execute(request) as ImageResult.Success
imageSuccess.resultCacheKey

Read and write cache

You can access the result cache by obtaining the result cache instance through the sketch.resultCache property, but be careful to obtain the lock before accessing, so as to avoid problems under multi-threading, as follows:

scope.launch {
    val resultCache = sketch.resultCache
    val resultCacheKey = requestContext.resultCacheKey
    resultCache.withLock(resultCacheKey) {
        // get
        openSnapshot(resultCacheKey)?.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(resultCacheKey)
        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(resultCacheKey)
    }

    // Clear all
    resultCache.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 results 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