Upgrading to Coil 3.x¶
Coil 3 is the next major version of Coil that has a number of major improvements:
- Full support for Compose Multiplatform including all major targets (Android, iOS, JVM, JS, and WASM).
- Support for multiple networking libraries (Ktor and OkHttp). Alternatively, Coil can be used without a network dependency if you only need to load local/static files.
- Improved Compose
@Previewrendering and support for custom preview behavior viaLocalAsyncImagePreviewHandler. - Important fixes for bugs that required breaking existing behaviour (outlined below).
This document provides a high-level overview of the main changes from Coil 2 to Coil 3 and highlights any breaking or important changes. It does not cover every binary incompatible change or small behaviour changes.
Using Coil 3 in a Compose Multiplatform project? Check out the samples repository for examples.
Maven Coordinates and Package Name¶
Coil's Maven coordinates were updated from io.coil-kt to io.coil-kt.coil3 and its package name was updated from coil to coil3. This allows Coil 3 to run side by side with Coil 2 without binary compatibility issues. For example, io.coil-kt:coil:2.7.0 is now io.coil-kt.coil3:coil:3.0.0.
The coil-base and coil-compose-base artifacts were renamed to coil-core and coil-compose-core respectively to align with the naming conventions used by Coroutines, Ktor, and AndroidX.
Network Images¶
coil-core no longer supports loading images from the network by default. You must add a dependency on one of Coil's network artifacts. See here for more info.. This was changed so consumers could use different networking libraries or avoid a network dependency if their app doesn't need it.
Additionally, cache control headers are no longer respected by default. See here for more info.
Multiplatform¶
Coil 3 is now a Kotlin Multiplatform library that supports Android, JVM, iOS, macOS, Javascript, and WASM.
On Android, Coil uses the standard graphics classes to render images. On non-Android platforms, Coil uses Skiko to render images. Skiko is a set of Kotlin bindings that wrap the Skia graphics engine developed by Google.
As part of decoupling from the Android SDK, a number of API changes were made. Notably:
Drawablewas replaced with a customImageinterface. UseDrawable.asImage()andImage.asDrawable(resources)to convert between the classes on Android. On non-Android platforms useBitmap.asImage()andImage.toBitmap().- Usages of Android's
android.net.Uriclass were replaced a multiplatformcoil3.Uriclass. Any call sites that passandroid.net.UriasImageRequest.dataare unaffected. CustomFetchers that rely on receiving anandroid.net.Uriwill need to be updated to usecoil3.Uri. - Usages of
Contextwere replaced withPlatformContext.PlatformContextis a type alias forContexton Android and can be accessed usingPlatformContext.INSTANCEon non-Android platforms. UseLocalPlatformContext.currentto get a reference in Compose Multiplatform. - The
Coilclass was renamed toSingletonImageLoader. - If you're implementing
ImageLoaderFactoryin your custom AndroidApplicationclass, you'll need to switch to implementingSingletonImageLoader.Factoryas a replacement forImageLoaderFactory. Once you implementSingletonImageLoader.Factory, you'll be able to overridenewImageLoader()if you need or want to override it.
The coil-svg artifact is supported in multiplatform, but the coil-gif and coil-video artifacts continue to be Android-only (for now) as they rely on specific Android decoders and libraries.
Compose¶
The coil-compose artifact's APIs are mostly unchanged. You can continue using AsyncImage, SubcomposeAsyncImage, and rememberAsyncImagePainter the same way as with Coil 2. Additionally, this methods have been updated to be restartable and skippable which should improve their performance.
AsyncImagePainter.stateis now aStateFlow. It should be observed usingval state = painter.state.collectAsState().AsyncImagePainter's defaultSizeResolverno longer waits for the firstonDrawcall to get the size of the canvas. Instead,AsyncImagePainterdefaults toSize.ORIGINAL.- The Compose
modelEqualityDelegatedelegate is now set via a composition local,LocalAsyncImageModelEqualityDelegate, instead of as a parameter toAsyncImage/SubcomposeAsyncImage/rememberAsyncImagePainter.
General¶
Other important behavior changes include:
- First party
Fetchers andDecoders (e.g.NetworkFetcher.Factory,SvgDecoder, etc.) are now automatically added to each newImageLoaderthrough a service loader. This behaviour can be disabled withImageLoader.Builder.serviceLoaderEnabled(false). - Remove support for
android.resource://example.package.name/drawable/imageURIs as it prevents resource shrinking optimizations. It's recommended to passR.drawable.imagevalues directly. Passing the resource ID instead of the resource name will still work:android.resource://example.package.name/12345678. If you still needs its functionality you can manually includeResourceUriMapperin your component registry. - A file's last write timestamp is no longer added to its cache key by default. This is to avoid reading the disk on the main thread (even for a very short amount of time). This can be re-enabled with
ImageRequest.Builder.addLastModifiedToFileCacheKey(true)orImageLoader.Builder.addLastModifiedToFileCacheKey(true). - Output image dimensions are now enforced to be less than 4096x4096 to guard against accidental OOMs. This can be configured with
ImageLoader/ImageRequest.Builder.maxBitmapSize. To disable this behavior setmaxBitmapSizetoSize.ORIGINAL. - Coil 2's
ParametersAPI was replaced byExtras.Extrasdon't require a string key and instead rely on identity equality.Extrasdon't support modifying the memory cache key. Instead, useImageRequest.memoryCacheKeyExtraif your extra affects the memory cache key. - Many
ImageRequest.Builderfunctions have moved to be extension functions to more easily support multiplatform.