Hello, regarding this <question> on stackoverflow,...
# compose
f
Hello, regarding this question on stackoverflow, Chuck Jazdzewski gave quite a detailed answer, but I'm trying to understand the real purpose of manually annotating a function or a property with the
@Stable
annotation since it seems that it doesn't affect skipping. Is it just useful for documentation purposes, or is it used by the compiler in some way?
s
It is used by compiler to figure out if the expression is stable, e.g. 10.dp It basically says that function result is stable if all parameters to the function are stable
e
What is the benefit of the function result being stable? If the result's type isn't stable then can anything be inferred from it? And if the type is stable, then wouldn't it be stable anyways?
e
if the result's type isn't stable then
@Stable
on the function isn't useful
if the function parameters and result are all stable, then it is still not necessarily the case that the function is pure, but
@Stable
indicates that it is
f
Thank you for your answers. From my testing and also what Chuck says, a function or a property annotated with
@Stable
are not skipped or memoized. Do you have an idea of how this stability would be used by Compose? What kind of benefits/optimizations can we expect?
a
Isn’t this another name for calling a function Pure? And, isn’t it so that most functions will be pure/stable?
e
if the function parameters and result are all stable, then it is still not necessarily the case that the function is pure, but @Stable indicates that it is
So if the input and result are stable, but the function isn't marked
@Stable
does the compiler treat that result differently than if the function is marked
@Stable
?
s
These values are mostly used for inferring if value is ever going to change E.g. we know that int/string constants are constant and there's no point comparing two instances of it to determine skipping. A stable modifier (e.g. padding) produced from that value also effectively never changes, so we don't compare those values either. Note that this data flow analysis is pretty brittle atm, so we don't expect anyone to use this annotation on their own functions. It currently only catches common cases like someone specifying padding/background modifier with const values, I believe.
As a short answer, stable function is expected to match the states defined here from parameters to results: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt If the input value is
Static
(for constants) or
Same
(e.g. values were compared before), it is assumed safe to propagate this state to the result of the stable function.
e
So in the following snippet
result
would have a stability of `Unknown`:
Copy code
@Immutable
object Foo

fun foo(param: Int) = Foo

@Composable
fun Foo() {
  val result = foo(1)
  Bar(result)
}
and in the following snippet it would be `Static`:
Copy code
@Immutable
object Foo

@Stable
fun foo(param: Int) = Foo

@Composable
fun Foo() {
  val result = foo(1)
  Bar(result)
}
s
Uncertain
in the first case, but correct otherwise