https://kotlinlang.org logo
Title
d

Daniel Okanin

07/03/2022, 4:23 PM
Hi everyone ! Im using the compose metrics and I get the following declare class: What is mean my class is stable but includes unstable fields? How is it effect? Is it effect if the function that uses this class be considers as skippable or not only? Is it ok to put “stable” annotation on class that includes unstable fields?
stable class ProViewModelItem {
  unstable val profileImage: ImageDescriptor?
  unstable val coverImage: ImageDescriptor?
  stable val numReviews: Int
  stable val reviewRating: Float
} 

This is how I declare this class:
@Stable
class ProViewModelItem(
    id: String?, title: String?,
    val profileImage: ImageDescriptor? = null,
    val coverImage: ImageDescriptor? = null,
    val numReviews: Int = 0,
    val reviewRating: Float = 0f,
) : HomeFeedViewModelItem(id, title)
f

Francesc

07/03/2022, 5:16 PM
stable
is a contract. It's ok if you uphold your part. How's your ImageDescriptor defined?
d

Daniel Okanin

07/03/2022, 5:17 PM
@Francesc as java interface
1. The result of
equals
will always return the same result for the same two instances. 2. When a public property of the type changes, composition will be notified. 3. All public property types are stable. SO i dont uphold my pard?
f

Francesc

07/03/2022, 5:41 PM
Stable means that it can change but any change will be notified. Does your class actually change? If it's immutable but the compiler can't infer it, you can mark it as Immutable.
d

Daniel Okanin

07/03/2022, 6:03 PM
I see, so if I have unstable fields in my class and @Stable annotation, there is any negative effect?
s

Stylianos Gakis

07/03/2022, 6:06 PM
If you say that something is @Stable but it is not you are making the compiler make a wrong assumption therefore you can not be guaranteed that things will work correctly. Things will most likely behave wrong without any warning. Aka never do this. I’d also recommend taking a look at this which was published recently https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8
f

Francesc

07/03/2022, 6:07 PM
Yes, that will cause issues. Usually you don't have to worry about recomposition, only if you see a performance issue would you need to delve into it. Adding the annotation when it does not apply will lead to subtle bugs
d

Daniel Okanin

07/03/2022, 6:12 PM
@Stylianos Gakis @Francesc Thanks
👍 1
Hi @Francesc after mark @immutable annotation on class that includes object from other module that not support compose (so its automaticily marked as unstable) I see the the inner field is still unstable but the the outer is stable, is it ok?
stable class PhotoViewModelItem {
  unstable val imageDescriptor: ImageDescriptor?
  stable val isSaved: MutableState<Boolean>
  stable val photoType: PhotoType?
  stable val tagsCount: Int
}
f

Francesc

07/07/2022, 9:31 PM
if you control the module where the
ImageDescriptor
is defined, you could annotatte it there. If you don't, you could wrap it in a class and mark it as
@Immutable
- assuming the implementation is indeed immutable. This stuff was recently described here https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8
d

Daniel Okanin

07/07/2022, 9:45 PM
yes I read this blog post, see the example of the data class Snack - he puts @immutable annotation and still use Set as field (its known as unstable)
f

Francesc

07/07/2022, 9:46 PM
right, you can annotate something with @Stable or @Immutable to help the compiler, but then you are responsible for honoring that contract
d

Daniel Okanin

07/07/2022, 9:48 PM
and what is the contract with immutable? Just the object will never change after it created yes?
f

Francesc

07/07/2022, 9:55 PM
the contract is basically that as long as
equals
and
hashCode
do not change, the object does not change. If it's immutable (doesn't change after construction) then those hold
as far as I understand it, the compose compiler relies on
equals
to determine if it needs to recompose for immuable objects. If you use data classes you get that for free, otherwise you have to write the
equals
to ensure a new, different object , does not yield the same
equals
(you could break that if you omitted a field, for instance)
d

Daniel Okanin

07/07/2022, 10:02 PM
Thanks a lot
👍 1