Hi Everyone, I am working on an Image Composable t...
# compose
h
Hi Everyone, I am working on an Image Composable that can take an image URL, measure its width, append a width query parameter to the URL and load the image. I am using it in a Horizontal Pager. The problem is that it is recomposing each time I swipe the images. Can anyone help me understand the problem?
Copy code
@Composable
fun Image(
    imageUrl: String,
    placeholder: Painter,
    contentDescription: String,
    modifier: Modifier = Modifier,
) {
    var size: IntSize by remember { mutableStateOf(IntSize.Zero) }

    val url by remember(size) {
        derivedStateOf {
            if (size == IntSize.Zero) {
                imageUrl
            } else {
                addOrUpdateQueryParameter(
                    url = imageUrl,
                    queryParam = WidthParam to size.width
                )
            }
        }
    }

    AsyncImage(
        model = url,
        placeholder = placeholder,
        contentDescription = contentDescription,
        modifier = modifier.onGloballyPositioned {
            if (it.size != IntSize.Zero) {
                size = it.size
            }
        }
    )
}
🧵 1
i
Are you able to share the code where you are using the Image method?
h
Yes sure,
Copy code
@Composable
fun ImageItem(
    imageUrl: String,
    onImageClick: () -> Unit = {}
) {
    Image(
        imageUrl = imageUrl,
        placeholder = painterResource(R.drawable.placeholder_2_3),
        contentDescription = "Product Image",
        modifier = Modifier
            .aspectRatio(2 / 3f)
            .testTag(imageUrl)
            .clickable { onImageClick() }
            .fillMaxSize())
}
i
It is hard to tell (for me anyways) without looking deeper into the code where it's coming from... if the size changes at all in the transition period I would start looking there... that would be the obvious thing making it update
h
I understand. I am using simple Horizontal Pager without any size changes. If I don’t get the size of the Image, it works perfectly fine. The strange things is that it recomposes even If I don’t use the remembered state
url
instead just use the
imageUrl
directly. Means if I just update the remembered state, it recomposes.
i
Maybe try using
onSizeChanged
modifier instead of globally positioned... i tested this with a label and image and it does not recompose.. i do not have a url handy to test with the url though
a
Try
BoxWithConstraints
🚫 1
s
Resurrecting this, as I'm trying to achieve the same thing. I can do it with BoxWithConstraints, but I'm wondering if there's a better way around this, since I heard a lot of concerns about performance with BWC/Subcompose and I might have dozens of these on screen at once.
b
Yes, you should not use BoxWithConstraints for this. You can do it with an interceptor instead. This is how its done in Crane https://github.com/android/compose-samples/blob/main/Crane/app/src/main/java/androidx/compose/samples/crane/util/UnsplashSizingInterceptor.kt#L27
âž• 1
s
Awesome! Thanks Ben!