Not able to understand viewmodel example on android dev site
Asked Answered
C

1

7
class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData<List<User>> {
        return users
    }

    private fun loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

Am trying to implement this way and its not compiling :

class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<String>> by lazy {
        return MutableLiveData().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData<List<String>> {
        return users
    }

    private fun loadUsers() {
        users.postValue(listOf("Tarun", "Chawla"))
    }
}

Mostly am not understanding the by lazy here. The example on android website seems wrong as loadUsers() is not returning anything which can be a delegate for users. can you please help me understanding above piece of code.

=======================================================

This is how I implemented:

    private val users : MutableLiveData<List<String>> by lazy {
        MutableLiveData<List<String>>().also {
            loadUsers(it)
        }
    }
    init {
        Log.e("Tarund", "View Model created")
    }

    override fun onCleared() {
        super.onCleared()
        Log.e("Tarund", "View Model deleted")
    }

    fun getUsers(): LiveData<List<String>> {
        return users
    }

    private fun loadUsers(users : MutableLiveData<List<String>>) {
        users.postValue(listOf("Tarun", "Chawla"))
    }
}

But if anyone can confirm if first example code above which I copy pasted from : https://developer.android.com/topic/libraries/architecture/viewmodel#kotlin is wrong

Chemush answered 6/5, 2020 at 15:49 Comment(3)
also scoping function output is context object. thus, if first access users property then return MutableLiveData() and call loadUsers functionDiscernible
Hey sorry, the code which I implemented is giving compile errors. Also can you please explain a little what you said above?Chemush
Am trying to understand why my implementation did not compiled and how by lazy is returning mutable users data when loadUsers() is not returning anything.Chemush
G
8

The code in the Android documentation is wrong.

The lazy construction itself is fine: loadUsers() doesn't need to return anything because the function also is defined as:

inline fun <T> T.also(block: (T) -> Unit): T

that means that in here:

private val sources: String by lazy {
    String().also {
      loadSources()
    }
}

the block also {} will return the empty String created with String() that can be assigned using lazy initialization to the val users

The error trying to compile the Android docs code is:

Type inference failed: Not enough information to infer parameter T in constructor MutableLiveData()

that means that the compiler is not able to infer the type of the MutableLiveData instance created using the constructor wihtout type.

Without the apply block the compiler will be able to compile it because it can easily infer the type from the val definition:

private val sources: MutableLiveData<List<User>> by lazy {      
    MutableLiveData()
}

but adding the apply block goes back to the generic type and the compiler cannot infer it. So the solution, as you did, is specifying the type hold in the MutableLiveData container:

private val sources: MutableLiveData<List<User>> by lazy { 
    MutableLiveData<List<User>>().also {
        loadSources()
    }
}
Guinea answered 29/5, 2020 at 15:16 Comment(1)
Another problem with that code is also that if you write sources.value = getValue() in loadSources loadSources gets called again! but only a 2nd time, I'm trying to figure out this already the whole day and still don't know whats wrong.Underwaist

© 2022 - 2024 — McMap. All rights reserved.