Image Loading in Jetpack Compose

Jetpack Compose is a modern toolkit for building native UI on Android. It simplifies and accelerates UI development with declarative and reactive programming. One of the common tasks in UI development is to display images from various sources, such as network, local storage, assets or resources. In this blog post, we will explore how to load images in Jetpack Compose using different libraries and techniques.

Loading images from disk

To load an image from disk, such as a PNG, JPEG, WEBP or vector resource, we can use the Image composable with the painterResource API. The painterResource function takes an image reference (such as a resource ID) and returns a Painter object that can be used to draw the image on the screen. We don’t need to know the type of the asset, just use painterResource in Image or paint modifiers1.

For example, to load an image from a resource:

Image( painter = painterResource(id = R.drawable.dog), contentDescription = stringResource(id = R.string.dog_content_description) )

To ensure that our app is accessible, we should supply a contentDescription for visual elements on screen. TalkBack reads out the content description, so we must ensure that the text is meaningful if read out loud and translated. In the above example, we use a stringResource function to load up the translated content description from the strings.xml file. If our visual element on screen is purely for visual decoration, we can set our contentDescription to null for the screen reader to ignore it1.

If we need lower-level ImageBitmap specific functionality, we can use ImageBitmap.imageResource function to load up a bitmap. For more information on ImageBitmaps, read the ImageBitmap versus ImageVector section1.

Loading images from the internet

To load an image from the internet, there are several third-party libraries available that can help us handle the process. Image loading libraries do a lot of the heavy lifting for us; they handle both caching (so we don’t download the image multiple times) and networking logic to download the image and display it on screen1.

Some of the popular image loading libraries for Jetpack Compose are:

To use any of these libraries in our Android app, we need to add the corresponding dependency to our build.gradle file. Then, we can use their provided composables or extensions to load an image from a URL.

For example, to load an image with Coil:

AsyncImage( model = "https://example.com/image.jpg", contentDescription = "Translated description of what the image contains" )

To load an image with Glide:

GlideImage( model = "https://example.com/image.jpg", contentDescription = "Translated description of what the image contains" )

To load an image with Fresco:

FrescoImage( model = "https://example.com/image.jpg", contentDescription = "Translated description of what the image contains" )

To load an image with Landscapist:

NetworkImage( imageUrl = "https://example.com/image.jpg", contentDescription = "Translated description of what the image contains" )

We can also configure the requests with optional parameters or lambdas to customize the loading behavior and appearance of the images.

Code examples

Here are some code examples of using different libraries to load images from the internet in Jetpack Compose:

Loading an image with Coil

AsyncImage( model = "https://coil-kt.github.io/coil/logo.svg", contentDescription = "Coil logo", modifier = Modifier.size(200.dp), loading = { Box(Modifier.matchParentSize()) { CircularProgressIndicator(Modifier.align(Alignment.Center)) } }, error = { Image( painter = painterResource(id = R.drawable.error), contentDescription = "Error image" ) } )

Loading an image with Glide

GlideImage( model = "https://coil-kt.github.io/coil/logo.svg", contentDescription = "Coil logo", modifier = Modifier.size(200.dp), requestBuilder = { crossfade(true) placeholder(R.drawable.placeholder) error(R.drawable.error) } )

Loading an image with Fresco

FrescoImage( model = "https://coil-kt.github.io/coil/logo.svg", contentDescription = "Coil logo", modifier = Modifier.size(200.dp), controllerBuilder = { autoPlayAnimations(true) placeholderImage(R.drawable.placeholder) failureImage(R.drawable.error) } )

Loading an image with Landscapist

NetworkImage( imageUrl = "https://coil-kt.github.io/coil/logo.svg", contentDescription = "Coil logo", modifier = Modifier.size(200.dp), loading = { ShimmerParams( baseColor = Color.LightGray, highlightColor = Color.White, dropOff = 0.65f ) }, failure = { Image( painter = painterResource(id = R.drawable.error), contentDescription = "Error image" ) }, success = { RevealCircularTransition( durationMillis = 600, delayMillis = 100 ) } )

%d bloggers like this: