compose中验证某个类型是否稳定的办法

6 阅读3分钟

compose中验证某个类型是否稳定的办法

在开启Strong Skipping mode的情况下:

  1. 如果某个类型被视为不稳定,则在判断是否跳过重组时使用===比较
  2. 如果某个类型被视为稳定,则在判断是否跳过重组时,先使用===比较,如果为false,再使用equals比较

用这个办法可以验证后续内容中类型是否稳定。

稳定

编译器将一个类型视为稳定有如下3种情况

1.视为稳定的特定类型

  • 所有基元值类型:Boolean、Int、Long、Float、Char 等。
  • 字符串
  • 所有函数类型 (lambda)

2.不使用@Stable注解时

用代码实验后发现在,不使用@Stable注解的情况下,,如果要让编译器认为这个类型是稳定的,需要满足如下2个条件:

  1. 所有属性(public/protected/privale)性被val修饰
  2. 属性指指向稳定类型
interface MyInterface {
    val name: String
}

class MyInter(override val name: String) : MyInterface 

MyInter会被编译器认为是稳定类型,因为name被val修饰并且指向稳定类型String。当进行这个判断时,只需要聚焦这2点,其他的什么都不用管。

官方文档里的要求不能准确的描述编译器的稳定性判断规则:

  1. The result of equals for two instances will forever be the same for the same two instances.
  2. If a public property of the type changes, Composition will be notified.
  3. All public property types are also stable.

第一点和编译器判断参数稳定性无关,例如:

private data class MyUnstable2(val value: String) {

    override fun equals(other: Any?): Boolean {
        val seed = System.currentTimeMillis()
        val boolenaValue = Random(seed).nextBoolean()
        return boolenaValue
    }

}

对于2个确定是MyUnstable2实例,上述equals实现会导致,它们有时相等,有时不相等;显然,违反了第一点,但是编译器依然将MyUnstable2类型视为稳定的。

第三点说的不准确,不止是public的属性,protected/private的属性也需要指向稳定类型才行

private  class MyUnstable3 {
    protected val random = Random(0)
}

private  class MyUnstable4 {
    private val random = Random(0)
}

MyUnstable3/MyUnstable4会被编译器认为是不稳定类型。因为它们都属性指向了不可变类型。

第二点也和编译器判断参数稳定性无关,例如:

private data class MyUnstable2(val value: MyProp)

@Stable
private data class MyProp(var value: String)

当修改MyProp的value属性时,显然没有通知Composition,这违背了第二点,但是编译器依然将MyUnstable2视为稳定的。

3.使用@Stable注解时

根据@Stable的源码,@Stable注解可以在如下地方使用:

  • 类/接口
  • 函数
  • 属性的get方法
  • 属性
@MustBeDocumented
@Target(
    AnnotationTarget.CLASS,
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY,
)
@Retention(AnnotationRetention.BINARY)
@StableMarker
public annotation class Stable

1.类/接口

如果在接口上使用,则这个接口的实现类型就是稳定的

@Stable
interface MyInterface {
    var name: String
}

// 1.MyInter被编译器认为是稳定类型
class MyInter(override var name: String) : MyInterface {
    override fun equals(other: Any?): Boolean {
        println("my inter equals function: $name")
        return super.equals(other)
    }
}

// 2.MyInterface2被编译器认为是稳定类型
interface MyInterface2 :MyInterface

interface MyInterface2 :MyInterface
// 3.face2对应的匿名类型实现了,所以这个匿名类型也被认为是稳定的
val face2 = object : MyInterface2 {

    override var name: String = "ggg"

    override fun equals(other: Any?): Boolean {
        println("run MyInterface2 equals method!")
        return super.equals(other)
    }

}