Image Loading (Coil & Glide) Quiz
DATA › Networking
Which statement best describes Coil?
- A Java-only image library that requires HttpUrlConnection for fetches
- A Kotlin-first, coroutine-based image loader with Compose support
- An RxJava-based image loader bundled directly into Jetpack Compose
- A bitmap pooling utility that manages memory but has no network layer
Answer: A Kotlin-first, coroutine-based image loader with Compose support
Coil (Coroutine Image Loader) is Kotlin-first, built on coroutines and Okio, and provides Compose composables like AsyncImage.
In Jetpack Compose with Coil, which API is the simplest way to display a remote image?
- Glide.with(context).load(url) into an ImageView view
- An ImageView(url) composable that wraps the URL
- AsyncImage(model = url, contentDescription = ...)
- Picasso.get().load(url) into a target view
Answer: AsyncImage(model = url, contentDescription = ...)
AsyncImage is Coil's primary Compose composable; Glide.with and Picasso are View-based, and there is no ImageView(url) composable.
Why does loading a full-resolution photo into a small thumbnail risk an OutOfMemoryError?
- Because disk caching is off by default, so every image reloads into memory
- Because the decoded bitmap uses the full pixel size, not the thumbnail size
- Because coroutines can leak heap memory when a load is cancelled mid-flight
- Because PNG files can’t be downsampled before decoding into a smaller bitmap
Answer: Because the decoded bitmap uses the full pixel size, not the thumbnail size
A bitmap's heap cost is width x height x bytes-per-pixel; without downsampling to the target size, a large image consumes far more memory than needed.
How do Coil and Glide prevent the wrong image from showing in a recycled RecyclerView row?
- They disable the memory cache for list rows to avoid stale images
- They load images synchronously so RecyclerView binding order stays fixed
- Binding the request to the target view cancels the prior in-flight load
- They always decode every image at full resolution before showing it
Answer: Binding the request to the target view cancels the prior in-flight load
Because each load is tied to the target ImageView, a new bind cancels the stale request, so only the latest request updates that view.
What does Glide.with(fragment) primarily provide beyond starting a load?
- Lifecycle integration that pauses and cancels requests
- Transparent encryption of every cached image on disk
- Automatic conversion of loaded bitmaps into vector drawables
- Guaranteed image decoding on the main UI thread
Answer: Lifecycle integration that pauses and cancels requests
Glide ties the request to the Fragment/Activity/View lifecycle, pausing on stop and clearing on destroy to avoid leaks and wasted work.
Which describes the typical lookup order in a two-tier image cache?
- Network first, then disk cache, then memory cache
- Memory cache first, then disk cache, then network
- Only the disk cache is checked before loading
- Memory cache, then network, and disk cache is skipped
Answer: Memory cache first, then disk cache, then network
The fast in-memory (decoded bitmap) cache is checked first, then the disk (encoded bytes) cache, and only then is the network hit.
Which is a correct difference between Coil and Glide?
- Glide alone supports Compose Multiplatform, whereas Coil does not
- Coil cannot load an image from a plain network URL
- Coil is Kotlin/coroutine-based; Glide is Java and View-based
- Both are written in Rust and share one common codebase
Answer: Coil is Kotlin/coroutine-based; Glide is Java and View-based
Coil is the modern Kotlin-first, Compose Multiplatform option; Glide is the mature Java/View library known for its BitmapPool and lifecycle integration.
What does Glide's default DiskCacheStrategy.AUTOMATIC do?
- It chooses a cache strategy based on source, like remote vs local
- It turns off disk caching completely to avoid using any storage space
- It always caches only the transformed result and never the original data
- It encrypts every file written to disk cache before storing it there
Answer: It chooses a cache strategy based on source, like remote vs local
AUTOMATIC chooses intelligently per data source, typically caching original data for remote images and the transformed resource for local/already-cheap sources.
What is the recommended way to use Coil's ImageLoader across an app?
- Create a new ImageLoader for each request so every image gets its own cache
- Use one shared ImageLoader configured once, since each one has its own caches
- Build the ImageLoader in each Activity.onCreate() on the main thread separately
- Use ImageLoader only for decoding video frames, not for loading regular images
Answer: Use one shared ImageLoader configured once, since each one has its own caches
Each ImageLoader has its own memory and disk caches, so sharing one singleton avoids duplicate caches and wasted memory; Coil exposes a default singleton for this reason.
When would you reach for rememberAsyncImagePainter instead of AsyncImage in Compose?
- When you need automatic disk caching, which AsyncImage does not offer
- When loading from the network, since AsyncImage only supports local files
- When you need a Painter for Image or Icon, or to draw it yourself
- Never, because rememberAsyncImagePainter has been removed from Coil
Answer: When you need a Painter for Image or Icon, or to draw it yourself
rememberAsyncImagePainter returns a Painter you can hand to any composable that accepts one or draw manually; AsyncImage is the higher-level component that wraps the load, layout, and draw together.
By default Coil decodes into hardware bitmaps (Bitmap.Config.HARDWARE) on supported API levels. What is the key benefit and caveat?
- They halve decode time but double heap usage, with no real downsides
- They are written to the disk cache as raw uncompressed pixels
- Their pixels can be read back freely on the CPU at any point
- Pixels stay in GPU memory, easing heap, but can't be read on CPU
Answer: Pixels stay in GPU memory, easing heap, but can't be read on CPU
Hardware bitmaps store pixels in graphics memory, easing heap and GC pressure, but you cannot read their pixels on the CPU, so operations needing pixel access force a software bitmap config.
You load the same image URL once plain and once with a CircleCropTransformation applied. How does the in-memory cache treat the two results?
- As two separate entries, since size and transformation are in the key
- As one shared entry, since the crop is applied only when the view draws
- Neither is cached in memory, because any transformation blocks caching
- Both are kept only on disk, and the memory cache ignores transformed bitmaps
Answer: As two separate entries, since size and transformation are in the key
The memory cache holds decoded bitmaps keyed by URL plus size and transformations, so the plain and circle-cropped versions are distinct keys and stored separately.
What capability does Coil's SubcomposeAsyncImage offer that AsyncImage does not?
- Loading remote images without declaring the INTERNET permission
- Distinct composable slots for loading, success, and error states
- Guaranteed lower overhead than AsyncImage inside a LazyColumn
- Disk caching of decoded results that plain AsyncImage skips
Answer: Distinct composable slots for loading, success, and error states
SubcomposeAsyncImage uses subcomposition so you can provide separate loading/success/error composable slots; the trade-off is higher cost, making it weaker for lazy item sizing.
In Coil 3, how is the HTTP networking layer handled?
- Networking is fixed to HttpURLConnection and can't be swapped
- Coil 3 dropped networking, so you fetch the bytes yourself first
- An optional add-on artifact lets you use OkHttp or Ktor for MPP
- Retrofit is required as a dependency for every Coil 3 image request
Answer: An optional add-on artifact lets you use OkHttp or Ktor for MPP
Coil 3 extracted networking into optional artifacts (coil-network-okhttp or coil-network-ktor), decoupling the core so it can run on Compose Multiplatform beyond Android.