问题现象
在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这里就不会重新设置一次数据了,指向的还是之前的对象
网友评论