Atul Gupta
03/19/2025, 9:18 AMderivedStateOf
like below(multiStateSheetState
is a AnchoredDraggableState
which has offset in it)
• Not using density
in remember key
val density = LocalDensity.current
val height = remember {
derivedStateOf {
maxSize - with(density) { multiStateSheetState.requireOffset().toDp() }
}
}
• Using density
in remember as key
val density = LocalDensity.current
val height = remember(density) {
derivedStateOf {
maxSize - with(density) { multiStateSheetState.requireOffset().toDp() }
}
}
which one is correct? requireOffset
is backed by a state object so should not be used as key. This is my understanding but I am not sure about the staticCompositionLocalOf
Stylianos Gakis
03/19/2025, 9:27 AMstatic
composition local is not in fact backed by mutableState, so your first option should not work.
If you are willing to give it a whirl, try to make your own static composition local and then change it to see how this would behave. I'd imagine it just lets the entire thing below its provider recompose, which will mean for option 1 the remember
will still be persisted so it will be showing stale data. But I am just guessing here, I do not actually know 😊Stylianos Gakis
03/19/2025, 9:28 AMval density = LocalDensity.current
val updatedDensity = rememberUpdatedState(density)
val height = remember {
derivedStateOf {
maxSize - with(updatedDensity) { multiStateSheetState.requireOffset().toDp() }
}
}
To see if that "fixes" it again. I believe it should.Albert Chang
03/19/2025, 10:02 AMdensity
is just a plain (final) variable. No matter where its value came from, what the lambda captures is the variable itself, not its source.
• So whether you need to specify density
as a key depends on whether it's mutable (and whether its properties are backed by mutable states). It's not.Stylianos Gakis
03/19/2025, 10:07 AMcompositionLocalOf
, which as far as I understand is backed by MutableState internally, then the first option would also work, right? Or do I misunderstand something here?Albert Chang
03/19/2025, 10:08 AMLocalDensity.current
, not LocalDensity.current
itself.Stylianos Gakis
03/19/2025, 10:09 AMval density = LocalDensity.current
val updatedDensity by rememberUpdatedState(density)
val height = remember {
derivedStateOf {
maxSize - with(updatedDensity) { multiStateSheetState.requireOffset().toDp() }
}
}
Should also work though right?Albert Chang
03/19/2025, 10:11 AMStylianos Gakis
03/19/2025, 10:26 AMAtul Gupta
03/19/2025, 12:58 PMBut density change rarely happens, so it's probably more efficient to just use it as a key.
density was just an example I could use other things as well like context or width
But why using as key is more efficient?Stylianos Gakis
03/19/2025, 1:12 PMAtul Gupta
03/19/2025, 1:18 PMrememberUpdatedState
) and remember(density)
one? Asking as you specifically mentioned rememberUpdatedState
so I am think it might be better or performant or handles more caseAtul Gupta
03/19/2025, 1:21 PMrememberUpdatedState
I think it's use to convert non state value(like function param) to state value so that anything reading from it like can get the updated valueMichael Krussel
03/19/2025, 1:40 PMremember
or derivedStateOf
.
Derived state is for when the child state is likely to change less often than what you are deriving from. The common example is whether something is visible based on the scroll state. Scroll state updates often, but the visibility of something inside it will only toggle at a given point. This makes it so recomposition (or layout or rendering) only happens when that boolean changes, and not when the scroll state happens. In this case, the value of height changes every time the requireOffset changes, so there's no benefit.
The calculation for height is very quick, so I would imagine the mechanics of remember will add more overhead then just recalculating it.Atul Gupta
03/19/2025, 1:43 PMval anchorHeight = remeber {
derivedStateOf {
val anchor = multiStateSheetState.anchors.closestAnchor(multiStateSheetState.offset, false)
val anchorPosInDp = anchor?.let {
multiStateSheetState.anchors.positionOf(anchor).toDpUsing(density)
} ?: maxSize
maxSize - anchorPosInDp // these will be fixed set of values based on the number of anchors
}
}