Travis Griggs
02/29/2024, 12:55 AM@Composable
fun foo(bar:Bar ... ) {
// this shows up every time the composition reruns with the parent changing the bar fed to it
"enteringComposition".logged()
// this will show up on initial, but on subsequent recalls, will not fire
var zork by remember(bar) { mutableStateOf(13).logged("simple") }
// this fires every time that bar is different too
var yak by remember(bar.uuid) { mutableStateOf(42).logged("derived") }
}
Alex Vanyo
02/29/2024, 1:02 AMequals
take into account the uuid
as part of its equals
?Travis Griggs
02/29/2024, 1:07 AMAlex Vanyo
02/29/2024, 1:08 AMvar zork by remember(bar.uuid)
and var yak by remember(bar.uuid)
are the sameTravis Griggs
02/29/2024, 1:08 AMAlex Vanyo
02/29/2024, 1:10 AMbar
a mutable object?Alex Vanyo
02/29/2024, 1:13 AMbar
passed to remember(bar)
is !=
to the new bar
passed to remember(bar)
.
But if the previous bar
and the new bar
are the same instance, because it is mutable, then the “previous” bar
and the “new” bar
are really the same bar
and are equal, even if the state inside (uuid
) has changed.Travis Griggs
02/29/2024, 1:25 AMTravis Griggs
02/29/2024, 1:26 AMTravis Griggs
02/29/2024, 1:29 AMoverride fun equals(other: Any?): Boolean {
return (other is DeviceAbstract) && this.oid == other.oid && other.javaClass == this.javaClass
}
(oid is it's "uuid"; class check is because it's a polymorphic class heirarchy and oids can be the same between different leaf types)Travis Griggs
02/29/2024, 1:46 AMvar lastValue = remember(value) { value }
where value is my fungible object that I'm passing in. If I print lastValue, it will stick the first value ever used. If I change it to:
var lastValue = remember(value.oid) { value }
then, it gets updated when value changes. So there must be some rules I'm supposed to use for "non primitive" things that get used in remember? I've glimpsed @Immutable and @Stable in some comment threads. Are they part of this puzzle? or something unrelated?Travis Griggs
02/29/2024, 1:58 AMTravis Griggs
02/29/2024, 2:01 AMBen Trengrove [G]
02/29/2024, 2:54 AMBen Trengrove [G]
02/29/2024, 2:55 AMBen Trengrove [G]
02/29/2024, 2:55 AMfun foo(bar: Bar = Bar())
Ben Trengrove [G]
02/29/2024, 2:56 AMvar
parameter, its not considered stableBen Trengrove [G]
02/29/2024, 3:06 AMStylianos Gakis
02/29/2024, 7:54 AMshikasd
02/29/2024, 3:33 PMTravis Griggs
02/29/2024, 5:51 PM*kotlinCompilerExtensionVersion* = *"1.5.8"
,* id(*"org.jetbrains.kotlin.android"*) _version_ *"1.9.22"* _apply_ *false*
, Studio = Hedgehog | 2023.1.1 Patch 2
• I do not know if I have strong skipping enabled. Where/what flag would that be?
• The type I am indicating as my compose function argument looks like:
abstract class ValveAbstract(override val oid: TwigID) : DeviceAbstract() {
var lock by mutableStateOf(ValvePosition.Unknown)
var position by mutableStateOf(ValvePosition.Unknown)
override var regions by mutableStateOf(emptyList<MappedRegion>())
...
actual instances passed in are of one of two concrete subclasses. The superclass indicated there looks like:
abstract class DeviceAbstract : Comparable<DeviceAbstract>, NameSaveable {
override var name by mutableStateOf<String?>(null)
...
It was annotating ValveAbstract as @Stable that made it behave as expected.
• The only default parameter on the function where this is occuring is the usual modifier. It looks like:
@Composable
fun RunIntervalFooter(valve: ValveAbstract, plans: PlansRepo, modifier: Modifier = Modifier) { ... }
Since this didn't turn out to be a simple question with a simple answer, I'll attempt to extract and reduce to a repeatably easily shareable example. And come back with a new question about that if I can reproduce. Thanks for all of the comments and help.shikasd
02/29/2024, 6:24 PMTravis Griggs
02/29/2024, 6:26 PMshikasd
02/29/2024, 7:20 PMbar
and new bar
are !=
on recompositions, so both remembers should trigger, but only the one with bar.uuid
does.
I don't think @Stable
should have any effect on remember
, it only matters for skippable functions and lambda memoization. (also stable and immutable are the same, just documentation difference).
You could try disabling intrinsic remember optimization which optimizes remember calls with a compiler parameter plugin:androidx.compose.compiler.plugins.kotlin:intrinsicRemember=false
See https://stackoverflow.com/questions/65545018/where-can-i-put-the-suppresskotlinversioncompatibilitycheck-flag on how to set them