How do the Android image loading libraries Glide and Fresco work internally?
Tier: CommonDifficulty: Hard
Glide and Fresco solve the same three problems internally, keep memory use down, avoid redundant work, and stay fast on repeat loads, through downsampling, a two level cache, and bitmap reuse.
- Downsampling. Neither library decodes an image at its full resolution if the
ImageViewit's going into is smaller. A 2000 by 2000 source image loading into a 400 by 400 view gets decoded straight to roughly 400 by 400, usingBitmapFactory.Options.inSampleSize, so the full resolution bytes never sit in memory in the first place. - Two level caching. A request checks an in memory cache of already decoded bitmaps first, then a disk cache of downloaded but possibly not yet decoded images, and only falls back to the network if both miss. A cache hit at either level skips the more expensive step below it, decode or download.
- Bitmap pooling. Instead of letting a bitmap that's scrolled off screen get garbage collected and allocating a fresh one for the next image, both libraries keep a pool of already allocated bitmaps of compatible size and hand them back out, loading new pixel data into that existing memory through
BitmapFactory.Options.inBitmap. This is what keeps scrolling aRecyclerViewfull of images from constantly triggering garbage collection pauses. - Lifecycle aware cancellation. Both libraries tie a request to the
ActivityorFragmentthat started it, and cancel in flight decodes and downloads the moment that screen is destroyed, so scrolling past ten images doesn't leave ten downloads still running for views nobody can see anymore.
The net effect of all four together is that a RecyclerView full of images stays smooth precisely because most of the expensive work, downloading, decoding, allocating, only happens once per image, and every scroll after that is serving from memory or reusing an existing bitmap's backing array instead of doing that work again.