Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to understand viewmodel example on android dev site

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

like image 499
Tarun Chawla Avatar asked May 06 '20 15:05

Tarun Chawla


People also ask

Can we use LiveData without ViewModel?

No, It is not mandatory to use LiveData always inside ViewModel, it is just an observable pattern to inform the caller about updates in data.

What is the difference between LiveData and ViewModel?

ViewModel : Provides data to the UI and acts as a communication center between the Repository and the UI. Hides the backend from the UI. ViewModel instances survive device configuration changes. LiveData : A data holder class that follows the observer pattern, which means that it can be observed.

How do you implement a ViewModel?

There are three steps to setting up and using a ViewModel: Separate out your data from your UI controller by creating a class that extends ViewModel. Set up communications between your ViewModel and your UI controller. Use your ViewModel in your UI controller.

Why do we need a ViewModel Android?

The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.


1 Answers

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()
    }
}
like image 57
fherrera Avatar answered Sep 20 '22 13:09

fherrera