A no-library, from-scratch low-tech image loader built to understand how libraries like Glide and Coil might work under the hood.
Instead of using Glide blindly, I built my own image loader to explore:
- What happens without downsampling?
- Can I reuse bitmaps safely?
- Does cancelling offscreen image loads help?
- What do GC and memory stats reveal during scroll?
-
Loads shuffled high-res images from Picsum
-
Displays in a
RecyclerView -
Benchmark flags:
data class BenchmarkConfig( val usePool: Boolean, val useDownsampling: Boolean, val useCancellation: Boolean )
-
Measures scroll time, memory usage, GC events, and network stats
-
Automated scroll flow for consistent results
- Cancel task if ViewHolder is recycled
- Decode via
BitmapFactory - Downsample based on
ImageViewsize - Try to reuse bitmap from custom pool
- Update UI only if still bound to correct image
| Feature | Impact |
|---|---|
| โ No Optimization | High memory, GC storms, janky scroll |
| โ Downsampling | Lower memory, faster decode, fewer GC events |
| โ Bitmap Pooling | Reduces allocations, tricky to get right |
| โ Task Cancellation | Huge win during flings, saves CPU & memory |
| ๐ All Combined | Smoothest scroll, minimal GC, lowest network use |
- Reusing bitmaps requires exact match +
inMutable=true - Downsampling is a no-brainer
- Cancellation improves UX and performance drastically
Donโt use this in production โ use Glide or Coil.
But if you're curious, bored, or want to learn: build one. You'll walk away with a deep understanding of bitmaps, memory, and image loading internals.