Lukasz Burcon
07/21/2021, 8:15 PM@Immutable and @Stable should really be used to make the most out of them. I couldn’t really find any use cases for them, as even marking a class with @Immutable annotation doesn’t mean it will always be skipped from recomposition after being altered (code in the thread). Does anyone have any code examples showing benefits of using either one?Lukasz Burcon
07/21/2021, 8:15 PM@Immutable
data class MyStateClass(
val foo: MutableState<String> = mutableStateOf("foo"),
var bar: String = "bar",
)
@Composable
fun Start() {
val foobar = remember { MyStateClass() }
Column {
FooBar(foobar)
}
LaunchedEffect(Unit) {
delay(1000)
foobar.foo.value = "bar"
foobar.bar = "foo"
}
}
@Composable
fun FooBar(name: MyStateClass) {
LogCompositions("Foobar")
Text(text = name.foo.value)
Text(text = name.bar)
}Lukasz Burcon
07/21/2021, 8:16 PMStart() composable, it then launches a delayed LaunchedEffect that modifies our “immutable” object. LogCompositions notifies me about 2 compositions that have happened, whereas I would expect just oneLukasz Burcon
07/21/2021, 8:22 PMShakil Karim
07/21/2021, 8:25 PMShakil Karim
07/21/2021, 8:26 PMLukasz Burcon
07/21/2021, 8:56 PMLuis
07/21/2021, 11:35 PMLuis
07/21/2021, 11:37 PMLuis
07/21/2021, 11:38 PMLuis
07/21/2021, 11:38 PMAdam Powell
07/22/2021, 3:16 PM@Immutable and @Stable do exactly the same thing today. @Immutable wouldn't exist as a Compose annotation except for it being an easier concept to explain to people than @Stable 🙂 if Kotlin had an immutable soft keyword or something we'd key off of that for the same optimizations.Adam Powell
07/22/2021, 3:19 PM@Immutable or @Stable that is less relevant todayAdam Powell
07/22/2021, 3:21 PMAdam Powell
07/22/2021, 3:26 PMMyStateClass is broken in two ways as declared at the beginning of the thread: it is a data class that declares a var constructor parameter (which arguably should be a compiler error for Kotlin in general since it leads to a whole lot of undesirable behavior in a system, e.g. if you ever use one as a hash table key) and it is declared as @Immutable when it is neither immutable nor stable.Adam Powell
07/22/2021, 3:34 PMMyStateClass would therefore better be declared as
class MyStateClass(
foo: String = "foo",
bar: String = "bar"
) {
var foo by mutableStateOf(foo)
var bar by mutableStateOf(bar)
}
and the stability should be inferred by the compose compiler plugin.Adam Powell
07/22/2021, 3:38 PMMyStateClass instances a and b are not .equals to one another; a != b, and this is correct. If a.foo changed, b.foo would not reflect that change, meaning that a and b are not stably equal.Adam Powell
07/22/2021, 3:46 PM@Composable function call if its stable parameters are equal to one another, because stably equal means that for all practical purposes, a is as good (and correct) as b. But if a and b are capable of changing independent of one another, a is not as good as b and that @Composable function call cannot skip and still be correct - it could be listening for changes to an old/stale object that will never come, but the newer object may continue to change. It must not skip that call because it needs to update and listen to the new object instead of the old.Shakil Karim
07/22/2021, 4:22 PMLuis
07/22/2021, 10:45 PMLukasz Burcon
07/23/2021, 11:18 AM