Image downloaded from internet are usually displayed with AsyncImage
, but the whole asynchronous thing won't work with @Preview
. It's a pity because preview is the fastest way of debugging the user interface.
However, there is one feature of AsyncImage
that does work even in preview - the placeholder
painter.
This quick workaround doesn't add much complexity and can be adapted to different cases:
- Check the image source.
- If it is an integer, then let's assume it is a
DrawableRes
identifier, and use it to initialize the painter for the placeholder.
- If it is a string, then it is probably a URL, so use the normal placeholder.
I'm adding an example of it :
@Composable
@Preview
fun SomeImageFromInternetPreview() {
SomeImageFromInternet(
src = R.drawable.some_test_image.toString())
}
@Composable
fun SomeImageFromInternet(src: String, modifier: Modifier = Modifier) {
// Things
// ...
// More things
// ...
AsyncImage(
// Preview mode will not even try to use the source:
model = src,
contentDescription = null,
// But preview will fetch the placeholder:
placeholder = placeHolderOrDrawableRes(src),
error = painterResource(id = R.drawable.broken_image),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.small),
contentScale = ContentScale.Fit)
// Yet more things
// ...
}
/**
* Returns a [Painter] that is either the one specified
* in the url, or a default value specified in the placeholder parameter.
* @param urlOrDrawableRes If it contains an integer, then use it
* as a [DrawableRes] instead of the placeholder.
* @param placeholder The [DrawableRes] to use if the
* url is not an integer.
* @return An initialised [Painter].
*/
@Composable
fun placeHolderOrDrawableRes(
urlOrDrawableRes: String,
@DrawableRes placeholder: Int = R.drawable.loading_image): Painter {
val drawableRes = urlOrDrawableRes.toIntOrNull()
return when {
drawableRes != null -> painterResource(id = drawableRes)
else -> painterResource(id = placeholder)
}
}