美文网首页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