Search code examples
androidandroid-jetpack-composecompose-recomposition

How do I avoid recompositions affecting animations?


I have an mp3 player I`m working on, but the animations are affected by recomposition

I believe this is causing the recomposition

  val playbackInfo: Flow<PlaybackInfo> = combine(
    audioPlaybackRepository.currentProgress,
    audioPlaybackRepository.currentDuration
) { progress, duration ->
    PlaybackInfo.TrackInfo(
        progress = if (duration != 0L) {
            progress.toFloat() / duration.toFloat()
        } else {
            0f
        },
        duration = duration.milliseconds,
    )
}

It`s being called here:

val playbackInfo by 
mainScreenViewModel.playbackInfo.collectAsState(PlaybackInfo.Unknown)

fun BottomSheet(
    playbackInfoProvider: () -> PlaybackInfo
) {
    ...
    val progress = playbackInfoProvider().progress
    val sliderMutableInteractionSource = remember { MutableInteractionSource() }
    ...
    SeekBar(
        ...
    onValueChangedFinished = {
     ...
        val positionInMS = getPositionInMs(
            sliderPosition,
            playbackInfoProvider().duration.toLong(DurationUnit.MILLISECONDS),
        )
    },
    )

    // the problem area where recompositions affect animation

    Animation(
        modifier = Modifier.align(Alignment.Center)
            .padding(bottom = if (isWide) 10.dp else 100.dp)
            .offset(y = if (isWide) -80.dp else 0.dp)
            .fillMaxSize(if (isWide) 0.6f else 0.85f),
        isPlaying = isPlaying,
        albumImage = currentSong?.image,
    )
}

This is what it causes, the composable recomposes (causing it to freeze) every time the Playback info changes:

enter image description here


Solution

  • Recompositon was caused by not reading the flows within the composable that needed the animation like @Captain Jacky suggested :). This as causing all the composables to recompose.

    Remedy:

        SeekBar(
        ...
    onValueChangedFinished = {
     ...
        val positionInMS = getPositionInMs(
            sliderPosition,
            // the fix
            playbackInfoProvider().value.duration.toLong(DurationUnit.MILLISECONDS),
        )
    },
    )
    

    I did the same with other composables that was adding to the recomposition.