Wael ElSawy
Wael ElSawy

Reputation: 73

Jetpack Compose animation performance issue

I'm new to Jetpack Compose, and I'm trying to rotate the home screen with animation when the menu button is tapped. It works fine 3-5 times, but suddenly it lags like crazy and I don't know why? Is this a bug, or am I doing something wrong?

enter image description here

var isOpen by remember { mutableStateOf(false) }
val transition = updateTransition(targetState = isOpen, "Menu")

val rotation by transition.animateFloat(
    transitionSpec = { spring(0.4f, Spring.StiffnessLow) },
    label = "MenuRotation",
    targetValueByState = { if (it) -30f else 0f }
)

val scale by transition.animateFloat(
    label = "MenuScale",
    targetValueByState = { if (it) 0.9f else 1f }
)

val translateX by transition.animateFloat(
    transitionSpec = { tween(400) },
    label = "MenuTranslation",
    targetValueByState = { if (it) 536f else 0f }
)

Box(
    modifier = Modifier
        .fillMaxSize()
        .graphicsLayer {
            cameraDistance = density * 10f
            rotationY = rotation
            scaleX = scale
            translationX = translateX
        }
) {
    HomeScreen()
}

Box {
   DefaultButton(
        onClick = { isOpen = ! isOpen },
        modifier = Modifier
            .padding(16.dp)
            .padding(top = 32.dp)
            .shadow(blur = 8.dp, radius = 16.dp)
            .size(32.dp, 32.dp),
        shape = Shapes.large,
    ) {
        Icon(
            imageVector = if (isOpen) Icons.Filled.Close else Icons.Filled.Menu,
            contentDescription = "Menu",
            tint = Color.Black,
        )
    }
}

Update #1

I found this in the logcat

Skipped 52 frames! The application may be doing too much work on its main thread. Davey! duration=1067ms; Flags=0, FrameTimelineVsyncId=2511155, IntendedVsync=4294436921331, Vsync=4294870254647, InputEventId=0, HandleInputStart=4294871069349, AnimationStart=4294871070287, PerformTraversalsStart=4294871939089, DrawStart=4294872039558, FrameDeadline=4294486921330, FrameInterval=4294870971954, FrameStartTime=41666666, SyncQueued=4294872645860, SyncStart=4295312217578, IssueDrawCommandsStart=4295312304089, SwapBuffers=4295937520703, FrameCompleted=4295944298047, DequeueBufferDuration=5729, QueueBufferDuration=166719, GpuCompleted=4295944298047, SwapBuffersCompleted=4295937862943, DisplayPresentTime=4237530536663, CommandSubmissionCompleted=4295937520703,

Update #2

The animation works flawlessly when I comment out all text components and vice versa. So what's wrong with the text components?

Upvotes: 2

Views: 1544

Answers (3)

Kaloyan Karaivanov
Kaloyan Karaivanov

Reputation: 31

I also had a similar problem.

In my case, I create a release version instead of a debug, it fixes it, but with the optimization mentioned in this Shrink, obfuscate, and optimize your app.

enter image description here

It is also good to apply other practices for optimizing the UI using the Layout Inspector.

Upvotes: 0

HendrikFrans
HendrikFrans

Reputation: 347

Drawing text is a surprisingly expensive operation, and not only in Compose. Text is generally drawn (serially) with the CPU, while an image is manipulated (in parallel) by the GPU.

Look at the Draw text section of the Compose Graphics Overview guide. It suggests using Modifier.drawWithCache to alleviate the expensiveness problem when drawing text in a DrawScope. I do not know if this will help when animating as you do.

Also, it does not explain why your animation works fine a few times, and then lags.

In a different context, I have drawn text once on a bitmap at the screen resolution, then animated the bitmap as an image for speed. You may want to try drawing your HomeScreen to a bitmap first.

Upvotes: 0

Halifax
Halifax

Reputation: 765

Please check the HomeScreen composable, component recomposition counts。

I suspect that HomeScreen reorganizes too many times。

You can just replace @Composable HomeScreen with an @Composeable Image verify。

Upvotes: 2

Related Questions