Reputation: 1695
I'm trying to emulate a Music player, and everything works, however using the layout inspector I can see that my image is being recompose every time that the "slider" value changes this is part of my code:
val albumArt by viewModel.albumArt.collectAsStateWithLifecycle() // collect a bitmap
val playbackPosition by viewModel.playbackPosition.collectAsStateWithLifecycle() // this cause a recomposition, it executes every second that is the duration of te song
@Composable
fun MusicAlbumArt(
albumArt: Bitmap?,
modifier: Modifier
) {
val painter = rememberAsyncImagePainter(
albumArt,
contentScale = ContentScale.Crop
)
AnimatedContent(targetState = painter,
transitionSpec = {
fadeIn() with fadeOut()
}) {
Image(
painter = painter,
contentDescription = null,
modifier = modifier,
contentScale = ContentScale.Crop
)
}
}
and this is the main composable:
@Composable
private fun MusicWidget(
playbackPosition: Float,
albumArt: Bitmap?,
){
BoxWithConstraints {
val width by remember { mutableStateOf(this.maxWidth) }
val height by remember { mutableStateOf(this.maxHeight) }
MusicAlbumArt(
modifier = Modifier.fillMaxSize(),
musicViewState = musicViewState,
albumArt = albumArt
)
//
MusicSlider(modifier = Modifier.fillMaxWidth()
}
The playbackPosition executes every second to update the "song duration" but analyzing this in the layout inspector the AnimatedContent
is skipped however the Image is recomposed every time, I can't find the wayt to avoid recomposition on the image. What could be the possible options?
Upvotes: 1
Views: 919
Reputation: 2892
Kind of difficult to tell what's going on without seeing more of the code but I would design a slot-based layout to fix it.
Something like:
@Composable
fun MusicWidget(
modifier: Modifier = Modifier,
albumArt: @Composable () -> Unit,
slider: @Composable () -> Unit
) {
BoxWithConstraints() {
albumArt()
slider()
}
}
then in your parent:
@Composable
fun Parent(
modifier: Modifier = Modifier,
viewModel: MusicViewModel
) {
val albumArt by viewModel.albumArt.collectAsStateWithLifecycle()
val playbackPosition by viewModel.playbackPosition.collectAsStateWithLifecycle()
MusicWidget(
albumArt = {
MusicAlbumArt(
albumArt = albumArt
)
},
slider = {
MusicSlider(
position = playbackPosition
)
}
)
}
Since compose function children are placed inside the lambdas of the slot api, they will only be recomposed if their input changes.
Upvotes: 0