Manuel Wrage
01/22/2020, 2:21 PMChuck Jazdzewski [G]
01/22/2020, 5:57 PMequals()
. For stable parameters the assumption is that we compare the previously passed values for all parameters and if equals()
returns true then recomposition is unnecessary as the result will be the same as last time. This is certainly true for naturally immutable values, such as String
and literals, but it is unclear for other data type. We use @Immutable
so a developer can indicate that the values of a type should be treated as if they are immutable. @Stable
can be used to indicate that, even though the type is not really immutable, it can be treated as one. For example @Model
is marked with @StableMarker
because it will invalidate the composition where it was read when it changes. We use @Stable
when the type is not immutable but the changes cannot, or will not, be observed during composition. Modifier
is the best example of this kind of type.
The main motivation for @Stable
and @Immutable
markers today is correctness of the generated code. It ensures we only assume we can skip composition when the types involved know, and are signed up for, the contract they are expected to obey.
In general, any object that can be mutated we should ignore the result of equals()
for skipping, it will always be true
even when the object has changed. Essentially we will be asking if a.equals(a)
which should always be true
. This doesn't tell us whether the composition will be the same for the value (as it won't be if the object is mutable and has changed) which is what we need to know for skipping. The exceptions for this are @Model
or similar objects as composition observes changes in these objects, or Modifiers
or similar objects where the mutations are not visible to composition (e.g. they are potentially updated with cached information during layout and draw) or object which are declared as mutable but generally are not (such as the result of deserialization from JSON or a protobuf).
We have considered inferring @Stable
some cases that seem reasonable such as any data
class that has only public val
properties, and any enum
class also with public val
properties (if any). Both involve a risk as a binary compatible change can be made to either of these types that adds a var
property which invalidates the code generation assumptions we have made for these types. In other words, even though the JVM and DEX consider these binary compatible changes, we would not.
As for the deserialization case we have some ideas along these lines but nothing concrete yet.