baltekg
baltekg

Reputation: 1223

LiveData "pass-by-reference" initial value

I have a ViewModel class that looks like this:

class EditUserViewModel(
    private val initUser: User,
) : ViewModel() {

    private val _user = MutableLiveData(initUser)
    val user: LiveData<User>
        get() = _user

    fun hasUserChanged() = initUser != _user.value

}

User can update some properties of the User data class instance through the UI.
To check if there are any changes when navigating from the fragment I use hasUserChanged method.
The problem is that is always false. I checked and it seems that the initialUser changes every time I change the _user MutableLiveData.
Why is that? Is the initial value of MutableLiveData passed by reference? I always thought that Kotlin is a "pass-by-value" type of language.

Update: The problem seems to disappear when copying initUser before putting it inside the MutableLiveData.

private val _user = MutableLiveData(initUser.copy())

But it still doesn't make sense to me why I have to do that.

Upvotes: 1

Views: 1175

Answers (1)

aminography
aminography

Reputation: 22832

Kotlin is like java and they are pass-by-value. If you implement the equals function in User class, or make it as data class (which implements the equals function implicitly), it makes you sure that the content of the user objects is checked by != operator.

Update

If you are changing the value of LiveData directly, for example like this:

_user.value.name = "some name"

it means that you are changing the name property of the initUser, because _user.value exactly refers to the object that the initUser does. Consequently, the != operator always returns false, because we have one object with two references to it.

Now, when you are doing so:

private val _user = MutableLiveData(initUser.copy())

you are creating a deep copy of initUser (let's call it X) which is a new object in memory with the same property values of initUser.

Thus, by changing its properties like: _user.value.name = "some name", in fact, you are making this change on X, not initUser. It leads to preserving the initial values in initUser, meaning do not changing them, and solving the issue.

Upvotes: 1

Related Questions