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