Kamel-Media / Kamel

Kotlin asynchronous media loading and caching library for Compose.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Lazy Column Item Performance issue

Polenoso opened this issue · comments

Using Compose Multiplatform ->

When using asyncPainterResource within a lazy colum or lazy row, the performance is broken under Android app, not happening in iOS App.

It seems the issue is related to the resource being held by the thread trying to download and paint the image.

We've tried to define a coroutine scope context specifically for each asyncPainterResource but the issue is still there.

Let us share the code we're testing:

@Composable
fun ArtWorkList(artworks: List<ArtWorkData>, modifier: Modifier = Modifier, isLoading: Boolean, onPagination: CoroutineScope.() -> Unit) {
    val lazyColumnState = rememberLazyListState()
    val shouldPaginate by remember { derivedStateOf {
        (isLoading && lazyColumnState.layoutInfo.totalItemsCount > 0 && (lazyColumnState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: -9) >= artworks.size - 1 && lazyColumnState.firstVisibleItemIndex != 0)
    } }

    LazyColumn(horizontalAlignment = Alignment.CenterHorizontally, state = lazyColumnState) {
        items(artworks) {artwork ->
            Card(modifier = Modifier.padding(6.dp), elevation = 4.dp) {
                Column {
                    ArtWorkImage(artwork.downloadUrl, modifier = Modifier.height(194.dp))
                    Text("By: ${artwork.author}", style = MaterialTheme.typography.h4)
                }
            }
        }
        item {
            if (isLoading) {
                LinearProgressIndicator()
            }
        }
    }
    LaunchedEffect(shouldPaginate, onPagination)
}

@Composable
fun ArtWorkImage(value: String, modifier: Modifier = Modifier) {
    val scope = rememberCoroutineScope()
    val resource = asyncPainterResource(data = Url(value), key = value) {
        coroutineContext = scope.coroutineContext
    }
    Box(modifier = modifier.border(BorderStroke(1.dp, Color.Black)), contentAlignment = Alignment.Center) {
        KamelImage(
            resource = resource,
            contentDescription = value,
            onLoading = { progress -> CircularProgressIndicator(progress) },
            onFailure = {
                Text(it.toString())
            }
        )
    }
}

@Serializable
data class ArtWorkData(
    val id: String,
    val author: String,
    val url: String,
    @SerialName("download_url")
    val downloadUrl: String
)

Even though the code is handling pagination, the issue happens without pagination.

Attaching a video where the app freezes without pagination enabled.

device-2023-06-13-140330.mp4

I'm not sure how to reproduce your example. If you can update the logic to load data I can take a look.

I'm not sure how to reproduce your example. If you can update the logic to load data I can take a look.

Hi, let me share the repository with you:

https://github.com/Polenoso/compose-multiplatform-tutorial

There you can find everything to test it.

Thanks

@luca992 @Polenoso I am having a similar issue running the app on Android. Additionally, I have observed using the memory profiler tool that the memory is also not getting released, and the RAM increasing drastically.
check out this video : https://youtu.be/v78eyXcYU7Q

Try @youranshul 0.6.1-SNAPSHOT, it has a performance fix to load images in a IO sub-scope of the composable's CoroutineScope. Now the asyn image loading coroutine will actually cancel when it goes off screen like it should. and if that doesn't help you are probably doing too much work on the main thread somewhere else like @Polenoso

@Polenoso your repo had a bunch of non kamel performance issues. Made a pr and explained further:
Polenoso/compose-multiplatform-tutorial#1 plus I updated it with the new snapshot which I think definitely did help. I lowered the filter quality too.... Those images are pretty massive however. I don't think you'll ever get amazing performance

@luca992 thanks!

Absolutely, I'm initiating to kotlin and compose so I knew it couldn't be just related to kamel, but it seemed that something could be happening behind the scenes that's why I opened the issue. Thanks for the help.

@luca992 thanks for the fix but My build is failing when I sync it with media.kamel:kamel-image:0.6.1 . This is my repo : https://github.com/youranshul/KmmMovieBuff

@luca992 thanks for the fix but My build is failing when I sync it with media.kamel:kamel-image:0.6.1 . This is my repo : https://github.com/youranshul/KmmMovieBuff

tried it... That's not a kamel issue. This is your issue

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0") {
    version {
        strictly("1.7.0")
    }
}