Hi, how to use `@Stable` annotation properly? From...
# compose
e
Hi, how to use
@Stable
annotation properly? From documentation
The result of
equals
will always return the same result for the same two instances.
So, should I override
equals
and
hashcode
methods for the following class?
Copy code
@Stable
class State (
    text: String,
    enabled: Boolean
) {
    var text by mutableStateOf(text)
    var enabled by mutablesStateOf(enabled)
}
I am not sure because I see a lot of
Stable
annotated classes where those methods are not overridden
👀 1
e
if you implement structural
equals
, that will not be a valid type for `@Stable`:
Copy code
val state1 = State("1", false)
val state2 = State("1", false)
state1 == state2
state2.text = "2"
state1 != state2
e
yes, I was talking about structural equals. Why is that not valid for
Stable
?
so the result for instances
state1
and
state2
is not the same 🤔
e
for comparison, a standard
@Stable
type:
Copy code
val state1 = rememberScrollState(initial = 0)
val state2 = rememberScrollState(initial = 0)
state1 != state2 // regardless of whether state1.value == state2.value
e
got it 👍 so the conclusion is that we never should override
equals
for
Stable
annotated classes. What about
@Immutable
annotation? As far as I understand, in that case we have to override those methods (considering that all other requirements are met)
e
I can't think of a practical application but "never" seems too strong. in principle this should be fine
Copy code
@Stable class Keyed(val key: String, private val map: SnapshotStateMap<String, String>) {
    var value: String by map
    override fun equals(other: Any?): Boolean = other is Keyed && key == other.key && map == other.map
    override fun hashCode(): Int = key.hashCode() * 31 + map.hashCode()
}
val map = remember { mutableMapOf("foo" to "hello", "bar" to "world") }
val state1 = Keyed("foo", map)
val state2 = Keyed("foo", map)
val state3 = Keyed("bar", map)
state1 == state2; state1 != state3; state2 != state3 // regardless of anything value is set to
also in principle an immutable type without structural equals (only referential equals) should be legal… it'll just be not useful for skipping
c
FWIW. I've shipped 4 apps to prod with compose without any real issues. I've never used @Stable 🙈