https://kotlinlang.org logo
#compose
Title
# compose
r

ritesh

03/23/2022, 6:56 AM
Can compose infer stability of a
sealed
class ?
Copy code
sealed class MyClass {
  object A :  MyClass()
  data class SomeClass(val value:String): MyClass()
}
g

gildor

03/23/2022, 7:10 AM
I think compose doesn’t infer stability automatically for user classes
👎 1
👍 1
You can mark it as @Stable though
r

ritesh

03/23/2022, 7:12 AM
It can infer for data class, say - if i have a data class with with val of primitives
I was wondering in this case if it can or not
Also, it should be @Immutable i believe if i have to mark it, not @Stable - as there is no reactive stream in the class
g

gildor

03/23/2022, 7:20 AM
Yeah, maybe for primitive val, not quite sure about it though
pretty sure it will not infer it from sealed class automatically
But you can try, it’s easy to check
Also, it should be @Immutable i believe
Yep, you right, Immutable
👍 1
r

ritesh

03/23/2022, 7:25 AM
But you can try, it’s easy to check
Ahh sure. thanks!
m

myanmarking

03/23/2022, 9:19 AM
so, is it ?
r

ritesh

03/23/2022, 4:18 PM
Not sure if i checked it correctly, but re-comp was skipped when using sealed class, same example as above https://twitter.com/mochadwic/status/1415860219213537282?s=19
Also, earlier i was under the impression that, something like this is not stable, when we do-not use
val
but use
var
Copy code
data class SomeClass(var value:String)
But re-comp was skipped in this case well, i believe it doesn't matter if it's
var
or
val
, compose considers all primitives as stable as mentioned in the documentation.
m

myanmarking

03/23/2022, 4:23 PM
don’t think it’s true. It was not skipped. The Composable that read that value was skipped because equals returns true
@Composable
fun SomeClassComposable(item: SomeClass){
Text(item.value)
}
SomeClassComposable entered body, but probably text will skip because content equals
r

ritesh

03/23/2022, 4:38 PM
Yeah, you are correct, i had made a mistake, while checking for data class stability,
var
or
val
does makes a difference.
Copy code
@Composable
fun ComposeTest(vm:MyVm){
    val dataClassstate = vm.state.value
    val sealedState = vm.sealedState.value
    LogCompositions(tag = "ComposeTest")
    Column {
        ButtonComposable(onClick = vm::valueChanged) // it changes sealedState, not dataClassstate state 
        SomeClassRecomp(someClass = dataClassstate)
    }
}

@Composable
fun SomeClassRecomp(someClass: SomeClass){
    LogCompositions(tag = "SomeClassRecomp")
    Text(text = someClass.value)
}
On Button click i am changing
sealedState
which ends of re-composing
ComposeTest
on every button click. If my
SomeClass
holds a
var
,
SomeClassRecomp
gets called irrespective of any change in it's state. But if i change it to
val
, it won't get called.
SomeClassComposable entered body, but probably text will skip because content equals
yeah and also it won't enter the SomeClassComposable body, if SomeClass is stable and haven't changed, it will enter even if equals returns true and but it isn't stable (example using
var
instead of
val
)
@Zach Klippenstein (he/him) [MOD] Sorry for tagging you in - would like to understand/know your pov on this as well.
z

Zach Klippenstein (he/him) [MOD]

03/23/2022, 5:39 PM
The best way to answer these questions is to just ask the compiler to tell you:
Copy code
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions {
        freeCompilerArgs += [
                "-P",
                "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${buildDir}/composeReports"
        ]
    }
}
Will spit out a file named something like
*-classes.txt
that describes what’s inferred for each class. So for your case, I get:
Copy code
stable class A {
  <runtime stability> = Stable
}
stable class SomeClass {
  stable val value: String
  <runtime stability> = Stable
}
stable class MyClass {
  <runtime stability> = Stable
}
today i learned 5
👀 3
r

ritesh

03/23/2022, 5:42 PM
This is great. Thanks.
z

Zach Klippenstein (he/him) [MOD]

03/23/2022, 5:43 PM
r

ritesh

03/23/2022, 9:51 PM
Had been exploring compiler metrics. It looks like compose does infer stability of sealed classes as well, no need to mark them Immutable.
Copy code
sealed class SealedClass{
    object Loading : SealedClass()
    data class SomeClass(val error:String):SealedClass()
}
Copy code
stable class Loading {
  <runtime stability> = Stable
}
stable class SomeClass {
  stable val error: String
  <runtime stability> = Stable
}
stable class SealedClass {
  <runtime stability> = Stable
}
What does
<runtime stability>
means? It's stability will be resolved at run-time? but it says Stable though
Copy code
<runtime stability> = Stable
For eg: Here, the
var
is stable, but at run-time it makes the class unstable. What does that mean, if just use
value
in a composable function, re-comp will be skipped, even though if it's a
var
?
Copy code
class AA {
    var value:String = "String"
}

unstable class AA {
  stable var value: String 
  <runtime stability> = Unstable
}
Copy code
class AA {
    val value:String = "String"
}

stable class AA {
  stable val value: String
  <runtime stability> = Stable
}
z

Zach Klippenstein (he/him) [MOD]

03/23/2022, 10:40 PM
What do you mean the
var
is stable?
A class with a var that’s not backed by a MutableState can’t be inferred to be stable because it probably doesn’t satisfy the contract of stability: if the var changes, the composition won’t be automatically notified
r

ritesh

03/24/2022, 4:17 AM
Copy code
unstable class AA {
  stable var value: String 
  <runtime stability> = Unstable
}
Yeah, I was referring to the fact that compiler says it's stable
stable var value: String
but also marks it as
unstable
at run-time. I think i got confused between run-time and compile-time stability inference. Makes sense in case of
var
Thanks
z

Zach Klippenstein (he/him) [MOD]

03/24/2022, 4:20 AM
I think that's because the property type, String, is stable, but not sure
👍 1
823 Views