WhollySoftware
Back to blogMobile

Handling Large Lists and Images Without Janky Scrolling

Wholly Software TeamDecember 9, 20245 min read
Handling Large Lists and Images Without Janky Scrolling

On a social app with a photo-heavy feed, early builds using a plain ScrollView with .map() over the full dataset held roughly 40MB of rendered views in memory and dropped below 20fps within a few hundred items. Switching to FlashList from FlatList, with estimatedItemSize set correctly, got us back to a consistent 58-60fps, because it recycles views instead of mounting every row.

Image handling was the second bottleneck. Decoding full-resolution photos — often 4000x3000 from modern phone cameras — on the main thread to display in a 350px-wide feed cell was the actual cause of jank, not the list itself. We moved to requesting server-resized variants — a CDN with on-the-fly resizing (Cloudinary in this case) serving a 2x-density thumbnail matched to the cell's actual rendered size, cutting average payload from 2.1MB to around 90KB per image.

Placeholder strategy matters more than people expect. Blurhash placeholders, computed server-side and stored as a short string alongside the image URL, gave us a perceived-performance win that a plain gray box didn't — user testing showed people scrolled more confidently when something resembling the final image appeared instantly instead of a blank flash.

We also cap how aggressively the list prefetches offscreen images. Prefetching too far ahead saturated the network on cellular connections and starved the visible row's own image request. Limiting prefetch to two screens ahead, combined with request cancellation when a cell scrolls out of the viewport before its image loads, brought time-to-first-meaningful-paint on the feed down from 1.8s to about 600ms on a mid-range Android device.

None of this is exotic technology — it's mostly about not doing unnecessary work on the main thread and not fetching more data than the screen can show. The lesson that keeps repeating across projects is that scrolling performance problems are almost always image decoding or list virtualization, rarely the list library itself.

PerformanceMobile UIReact NativeImage Optimization
Handling Large Lists and Images Without Janky Scrolling — Wholly Software