Building Carousel Part III: Drawing Images on Screen
Article Summary
Tina Wen from Dropbox tackles a deceptively hard problem: how do you render tens of thousands of photos at 60fps without turning your app into a slideshow of gray squares?
When building Carousel, Dropbox's photo app, the team hit a wall with image rendering. Decoding three 256px thumbnails took 30ms, but smooth scrolling requires each frame to render in just 16ms. The naive approach would drop frames constantly. Here's how they solved it.
Key Takeaways
- Decoding 256px thumbnails took 10ms each, making 60fps impossible with naive approach
- Dual thumbnail strategy: 75px for fast scrolling, 256px for quality when stopped
- Smart queue management: only decode high-res images when scrolling slows down
- Bitmap caching prevents re-rendering same images as users scroll back and forth
By combining low-res thumbnails on the main thread with background queuing of high-res images based on scroll velocity, Dropbox achieved smooth 60fps scrolling while maintaining image quality.
About This Article
Dropbox found that decoding a 512px thumbnail took 50ms, which was three times slower than a 256px thumbnail. This made high-resolution rendering too expensive for fast-scrolling scenarios where users need instant visual feedback.
Dropbox added scroll velocity detection using CADisplayLink callbacks. During fast scrolling, it renders 75px thumbnails on the main thread in about 2.7ms. When scrolling slows down, it queues 256px decoding jobs to background threads instead.
The configurable bitmap cache and intelligent queue management let thumbnail resolution swap smoothly. The render queue stays limited to one screen-full of decode jobs at most, which keeps CPU usage low.