I’m quite confused about recomposition here, I fol...
# compose
o
I’m quite confused about recomposition here, I followed this example https://developer.android.com/jetpack/compose/performance/layoutinspector, putting the value and the read inside the lambda, this composable pretty much wrapping the content that is below a collapsable header, I can see in recomposition count that it is recomposing every time the header is showing or collapsing during scroll (where offset is changing), any insight appreciated, thanks
Copy code
@Composable
fun MyBox(yProvider: () -> Float){
    Box(
        modifier = Modifier
            .fillMaxSize()
            .graphicsLayer {
                translationY = yProvider()
            }
            .background(
                color = Color(0XFF123456),
                shape = RoundedCornerShape(
                    topStart = 16.dp,
                    topEnd = 16.dp
                )
            )
    ){...} // even with no content, same result
}
call
Copy code
MyBox(
    yProvider = { scroll offset calculated here }
)
r
What is inside the
{...}
? And what happens if you comment all the lines that are inside
{...}
?
I'm blind:
This composable pretty much wrapping the content that is below a collapsable header
o
even with the box empty completely without {} it is still recomposing
r
I've never used
Color(0XFAFAIOS)
that way, what if you set
Color.Red
or empty background?
I can see in recomposition count that it is recomposing every time the header is showing or collapsing during scroll
So it's recomposing outside of
MyBox
composable?
o
(same result with no bg btw) this is what I see
r
That's weird, even though I haven't tried your example - I've done this multiple times and it shouldn't be recomposing 🤔
o
yes it’s quite weird, already spent way too much time trying to solve, I have the same with other composables but just trying to focus on this small one
r
I wonder what are you doing in the
yProvider
🤔 Are you using some unstable type or?
How do you calculate this:
yProvider = { scroll offset calculated here }
o
it’s a mutablestate that saves some offset and calculation is using that and some other data, but my understanding is having in a lambda should make that transparent
r
If you save some offset, you're reading the value in order to save it That's what could be causing the recomposition inside
MyBox
You're deferring this operation inside
MyBox
Whatever you're doing - accessing a property - is considered reading and since you're using lambda to defer the operation, all of this is happening inside
MyBox
Not sure if I explained myself correctly
Or maybe you're using some unstable type, I might be wrong in any of the 2 assumptions 😅
o
no that was clear 😄 thanks, Im just having trouble understanding why reading it “somewhere else” would affect recomposing MyBox, because in the compose example they’re even reading the value inside the lambda, so my guess is it shouldn’t make a difference for MyBox 🤔
r
Yep, that's a good question, unfortunately, I don't know how is that happening without any close-example of the lambda I'm pretty sure that the problem could be in that lambda but I don't know what it is 😅
o
so Im basically using
Copy code
object : NestedScrollConnection {
   override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
to save the offset and using it to update the
translationY
, and the yProvider is
Copy code
yProvider = {-state.scrollOffset + headerHeight}
so nothing crazy imo
r
What type is
State
? Is a custom class?
is it something like this?
data class CustomClass(val scrollOffset: Float)
o
yea saving some other stuff too
like consumed scroll and some flags
r
Alright, have you annotated that class with
@Stable
?
o
trying that now
nothing seems to be working for it, trying different stuff
r
Damn no idea, do you have any other custom classes inside that Custom class? As a last resource, I would check: https://github.com/androidx/androidx/blob/androidx-main/compose/compiler/design/compiler-metrics.md By adding just a few lines in gradle and building you get some valuable output that tells you if your composable functions or custom classes are unstable With that info it might help you to dig it up or discard
s
Im just having trouble understanding why reading it “somewhere else” would affect recomposing MyBox
If I understood correctly what you are not sure about there, I would very strongly recommended to reading this https://dev.to/zachklipp/scoped-recomposition-jetpack-compose-what-happens-when-state-changes-l78