美文网首页compose
observeAsState和data class 一同使用导致

observeAsState和data class 一同使用导致

作者: 肖散 | 来源:发表于2024-01-01 15:34 被阅读0次

    问题现象

    在model中定义

    var bean = MutableLiveData(DataBean())
    
    @Parcelize
    data class DataBean(
        @SerializedName("test")
        var test: String? = null,
    ) : Parcelable
    

    在compose中使用

     val beanStateValue = model.bean.observeAsState().value
    

    在model中从服务器拿到数据,然后设置值

      bean.value = it
    
    预期结果 实际效果
    每次设置bean的时候,beanStateValue 都应该收到变化,从而引起重绘 第一次设置正常, 在第二次设置bean的数值的时候,二者地址指向的地址不一致了beanV === bean .value 是false

    原因

    1.默认的 structuralEqualityPolicy 判断用的是 == 也就是 equals 方法 并不是 ===

    2.如果数据类 用了data类。data类的hashCode和 equals 方法是被重写了的,相当于只用来比较了其中值是否相等。

    如下测试类BB

    data class BB(
        @SerializedName("test")
        var test: String? = null,
    ) 
    
       public int hashCode() {
          String var10000 = this.test;
          return var10000 != null ? var10000.hashCode() : 0;
       }
    
       public boolean equals(@Nullable Object var1) {
          if (this != var1) {
             if (var1 instanceof BB) {
                BB var2 = (BB)var1;
                if (Intrinsics.areEqual(this.test, var2.test)) {
                   return true;
                }
             }
    
             return false;
          } else {
             return true;
          }
       }
    

    state 实际上是 SnapshotMutableStateImpl

        override var value: T
            get() = next.readable(this).value
            set(value) = next.withCurrent {
                if (!policy.equivalent(it.value, value)) {
                    next.overwritable(this, it) { this.value = value }
                }
            }
    

    然后在判断这里

    @Suppress("UNCHECKED_CAST")
    fun <T> structuralEqualityPolicy(): SnapshotMutationPolicy<T> =
        StructuralEqualityPolicy as SnapshotMutationPolicy<T>
    
    private object StructuralEqualityPolicy : SnapshotMutationPolicy<Any?> {
        override fun equivalent(a: Any?, b: Any?) = a == b
    
        override fun toString() = "StructuralEqualityPolicy"
    }
    

    注意! 这里用的是 == 所以,如果是用了 data class,并且,其中数值未改变, 会导致observeAsState后的值并不会更新。从而导致observeAsState指向的对象和实际model中的对象是两个不同的对象

    所以,第一次能刷新是因为MutableLiveData中初始化其中数据为空,设置了一个非空值,所以判断为不等,可以设置数据
    第二次未刷新,是因为,虽然从服务端拿到的数据是和第一次相同的,但是MutableLiveData中实际上已经是一个新的对象。但是由于数据一致,== 判断为true,observeAsState这里就不会重新设置一次数据了,指向的还是之前的对象

    相关文章

      网友评论

        本文标题:observeAsState和data class 一同使用导致

        本文链接:https://www.haomeiwen.com/subject/tnuundtx.html