首页 > 解决方案 > 为什么作者可以通过 update 将新对象重新分配给 val?

问题描述

标签: kotlin

解决方案


The val keyword only refers to which object the variable holds, not the data inside said object. For example:

class MyClass(var value: Int)

The following code is not allowed:

val obj = MyClass(5)
obj = MyClass(7) // compile error

because the val keyword refers to the variable itself being reassigned to a different object. This code, however, is allowed:

val obj = MyClass(5)
obj.value = 7

Here, obj is still the same object, only a property of said object changed value. In your provided code, the update function modifies data stored inside the _uiState object, however it does not swap it for a new object. This is important because:

var obj = MyClass(5)
val copy = obj
obj = MyClass(7)
println(copy.value) // prints 5
println(obj.value)  // prints 7

When reassigning a variable, the old object remains, and any other variables referencing that object are not updated. In your case, _uiState.value is modified, not the variable itself. Hope this clears things up!

Edit:

Yes, it.copy() is an expression which creates a new object. However, this code is executed in the line _uiState.update { it.copy(loading = true) }, in the refreshAll() function. As it is the last statement in a lambda expression (also the only one, but doesn't matter), it is the return value of said lambda. Here we have to look at the declaration of the update function.
The lambda is stored in the function variable (of type (T)->T). This means, whenever function() is called, the code inside the lambda is executed, and its result (a new object) is then returned by the function() call. This value is assigned to the val nextValue variable and not to _uiState itself. The compareAndSet function modifies _uiState.value and does not change the object the _uiState variable references.
And by the way, the object returned by it.copy() is of type T, and not of type MutableStateFlow<T>, which your _uiState variable holds. T is the type of _uiState.value.


推荐阅读