https://kotlinlang.org logo
#compose
Title
# compose
z

Zoltan Demant

11/25/2021, 4:37 PM
My
transition.AnimatedContent
block sometimes takes 500-1000 ms to execute. Is this a bug, or am I doing something wrong? 🧵👀
This is my code. I can verify that all other code runs <10 ms; its specifically the invokation of
AnimatedContent
itself which is super-slow, and it happens when the content passed in has a lot of data, e.g. in this case a list with ~300 items.
Copy code
val transition = stack
    .last()
    .let { top ->
        updateTransition(
            targetState = BackStackState(
                key = Compatible.findKey(top),
                content = top,
                size = size
            ),
            label = null
        )
    }

transition.AnimatedContent(
    contentKey = BackStackState::key,
    transitionSpec = {
        contentTransform(
            difference = targetState.size - initialState.size
        )
    },
    content = { state ->
        stateKeeper.SavedState(
            key = state.key,
            content = {
                Render(state.content)
            }
        )
    }
)

private fun contentTransform(
    difference: Int
): ContentTransform {
    return when {
        difference >= 0 -> {
            ContentTransform(
                targetContentEnter = slideInVertically(
                    initialOffsetY = { height -> height },
                    animationSpec = SlideSpec
                ),
                initialContentExit = fadeOut(
                    animationSpec = FadeSpec
                ),
                targetContentZIndex = 1f
            )
        }
        else -> {
            ContentTransform(
                targetContentEnter = fadeIn(
                    animationSpec = FadeSpec
                ),
                initialContentExit = slideOutVertically(
                    targetOffsetY = { height -> height },
                    animationSpec = SlideSpec,
                )
            )
        }
    }
}

@Immutable
private data class BackStackState(
    val content: Any,
    val key: String,
    val size: Int
)
Removing
content
from targetState fixes it, but how am I then to know which content to render in the content block of AnimatedContent?
z

Zach Klippenstein (he/him) [MOD]

11/25/2021, 7:53 PM
Does the problem scale with the size of the list? Does your key derivation function walk the whole list?
z

Zoltan Demant

11/26/2021, 6:31 AM
Yep, it seems to scale with how complex the screen itself is. The key is derived only from the screen itself, e.g. in this case my content is something like HistoryScreen (key=typeOf<HistoryScreen>) which in turn has the large list. Update: Its the hashCode function on my screen taking ~100 ms, and then being called a lot during the animation. I can work around it by wrapping the content in a
() -> Any
block. Not sure if thats a good idea in practice, or is it? Im really looking to transition screens from A -> B, rather than animate whenever A/B themselves change.
4 Views