coil icon indicating copy to clipboard operation
coil copied to clipboard

rememberAsyncImagePainter recomposes infinitely when state is observed

Open colinrtwhite opened this issue 1 year ago • 1 comments

Describe the bug rememberAsyncImagePainter recomposes infinitely if painter.state is observed and crossfade(true) or another configuration option is used.

To Reproduce

@Test
fun recomposesOnlyWhenStateIsObserved() {
    val compositionCount = AtomicInteger()

    composeTestRule.setContent {
        val painter = rememberAsyncImagePainter(
            model = ImageRequest.Builder(LocalPlatformContext.current)
                .data("https://example.com/image")
                .fileSystem(FakeFileSystem())
                .build(),
            imageLoader = imageLoader,
        )

        Image(
            painter = painter,
            contentDescription = null,
        )

        val state by painter.state.collectAsState()
        state.toString()

        when (compositionCount.incrementAndGet()) {
            1 -> assertIs<State.Empty>(state)
            2 -> assertIs<State.Loading>(state)
            3 -> assertIs<State.Success>(state)
            else -> error("too many compositions")
        }
    }

    assertEquals(3, compositionCount.get())
}

Version Coil 3.0.0-rc01

colinrtwhite avatar Oct 19 '24 20:10 colinrtwhite

To work around this issue, wrap your ImageRequest in a remember:

val context = LocalPlatformContext.current
val painter = rememberAsyncImagePainter(
    model = remember(context) {
        ImageRequest.Builder(context)
            .data("https://example.com/image")
            .crossfade(true)
            .build()
    },
    imageLoader = imageLoader,
)

colinrtwhite avatar Oct 19 '24 20:10 colinrtwhite