If an interface is annotated with `@Immutable`, bu...
# compose
z
If an interface is annotated with
@Immutable
, but is implemented as a value class that wraps a domain class (without
@Immutable
), does compose still consider it immutable? Code example in thread 🧵
Copy code
data class DomainPerson(
    val name: String,
)

@Immutable
interface ComposePerson {

    val name: String
}

@JvmInline
value class DomainPersonWrapper(
    val domainPerson: DomainPerson,
) : ComposePerson {

    override val name
        get() = domainPerson.name
}

@Composable
fun Person(person: ComposePerson) {
    // Is person still immutable if 'DomainPersonWrapper' is passed in?
}
f
Is it even valid to use
@Immutable
on interface? How can you make sure that some implementation will not be mutable? 🤔
z
Im just curious if it would work! 🙂
a
No. The compiler will look at the actual class.
But in the case of
Person
composable, the stability of
DomainPersonWrapper
doesn’t matter and what matters is the stability of
ComposePerson
.
z
@Albert Chang So, the compiler sees the end class, but the contract from
ComposePerson
still holds true and thus its immutable?
a
The compiler only looks at the declared parameter type, which in your case is
ComposePerson
. While it is a contract on child classes, it doesn’t necessarily make its child classes stable. For example if you have a
@Composable fun Person(person: DomainPersonWrapper)
, the parameter will be considered unstable.
z
That makes sense, thank you! And if I were to have
DomainPerson : ComposePerson
, DomainPerson would be considered @Immutable as well right? Just trying to make sure my understanding of it is correct 😄
a
No, DomainPerson won’t be considered stable but its stability doesn’t matter in your case anyway.
And that why you should be careful and make sure the type of the parameter you actually pass in is stable, otherwise the contract will break, resulting in incorrect behavior.
z
Hmm! Got it, Ive actually inherited a common @Immutable interface for my models that are rendered to make my life easier (they are immutable).. So that doesnt actually do what I thought it does mind blown
s
I would check the compiler metrics output for this matter to confirm I didn't dig deep into the compiler stability inference, but we do have a few Stable interfaces across the codebase (e.g. modifier), suggesting that compiler actually checks the parameter type of Composable function (e.g. ComposePerson in your case) for stability
On the unrelated note,
value
class passed as an interface will force Kotlin to box anyway, so
value
might be useless here
z
Ill do that, @shikasd. I dont want to optimize prematurely, but when the idea struck me I felt that I at least wanted to ask about it 😄 I had no idea that value classes could get boxed like that, but I guess it makes sense - how else would all the values be provided to the function? Thanks for teaching me something new! 🙂
I just had a chance to run the compiler metrics! • Using @Immutable interface as parameter to a composable function, I get restartable skippable, which is awesome. • Extending a @Immutable interface, does indeed mark the class @Immutable as well 🙂
s
Great to hear!
z
Is it possible to apply the compose compiler to a pure kotlin module? I do wonder how performance would be affected if all my domain models were stable, pretty much all my "inner" composables for screens are unstable currently as a result of the models sitting far away from compose. I guess applying the compiler would be a quick way to find out!
s
Do you mean MPP modules? It is possible, but there are some tricks involved Maybe jetbrains have a version that works out of the box
z
Value classes arent stable, regardless of @Stable, this is expected. But, a value class that wraps a @Stable value is also unstable, which doesnt make sense to me.
@shikasd Both yes/no. My domain module is actually just kotlin currently, does that work without any tricks?
s
If you don't have Android plugin included, then you have to configure compiler on your own, I think You can check how compose-jb configures that, most likely it is fairly simple
z
Ill take a look, thank you! 👍🏽
It actually made a huge difference, especially for animations. Hard to put into percentage, but maybe 25% smoother? Clearly noticeable at least. I was also able to verify that the value classes dont get boxed. So win win 👍🏽
164 Views