简体   繁体   中英

Android ViewModel responsibility is only hold data or hold data + controller for view?

From official we know

The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way

But i think lot of developers use ViewModel as both data store and controller(like calling repository, network client for data). I also use as for both data store and controller for view.

Android official sample code has also some controller logic. From official :

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.
  }
}

Here loadUsers may calling some Repository or NetworkClient . So here it acting like controller.

I am sure many developer do this way, but as from definition ViewModel should store and manage UI related data, should ViewModel act as a Controller ?

I found some stackoverflow thread this and this about this.

First one accepted answer suggested not to use use ViewModel as Controller and to use a Controller for other task.

In comment section of Second one @commonsware also suggested not to use complicated things other than data.

So my question is

  1. What will be the actual responsibility of ViewModel from architectural concept?
  2. If i have to do some method calls related to View [like data query, network call and other business login related stuff ] where should i do it?
  3. and if i have to use a Controller then how i connect View and Controller for device rotation and sharing controller between Fragment?

Hope my question is clear to all

Thanks in advance.

Here loadUsers() may calling some Repository or NetworkClient. So here it acting like controller.

I am sure many developer do this way, but as from definition ViewModel should store and manage UI related data, should ViewModel act as a Controller?

Theoretically, the retrieval of data should be internal to the LiveData , triggered by having active observers and based on that, deciding what to do (in onActive() ). If the LiveData is actually a MediatorLiveData , then this also applies to any block bound with addSource , as the block added with addSource of a MediatorLiveData is only called when the MediatorLiveData is observed by an active observer

You can see this technique used to its fullest in the NetworkBoundResource . The ViewModel only stores data, and knows nothing of data loading.

What will be the actual responsibility of ViewModel from architectural concept?

If you see the comments by Yigit Boyar (creator of ViewModel ):

I'm the guy (or part of the team) that added it and it had nothing to do w/ MVVM. It is all about trying to give a class to people where they should put the data.

AAC is not an MVVM implementation, nor VM concept only lives as part of MVVM.

In fact, the main motivation for this was; we've been telling devs not to manage data in the UI controller and the answers was also, so where? And ViewModel became that answer.

We want it to be the model for your view layer (fragment, activity whatever). On the hindsight, it could be better to pick a name that is new but naming is really hard.

In conclusion: ViewModel is the Model in an MVC scenario, where C is the Activity or Fragment, V is the inflated view, and M is the ViewModel .

If i have to do some method calls related to View [like data query, network call and other business login related stuff ] where should i do it?

ViewModel gets the data in the form of a LiveData, and the LiveData is "activated" by observing it from the View with a given lifecycle.

Network calls are supposed to be also triggered in the same manner (if you follow the approach as per LiveData was designed).

In theory, if you have a login call, you could as well do it in the controller instead of the model, so you could do it in the Fragment, even though there are tricks like Jetpack Databinding that would let you call methods from the View on the Model directly from the XML.

and if i have to use a Controller then how i connect View and Controller for device rotation and sharing controller between Fragment?

ViewModel exposes LiveData and can potentially also expose LiveEvent if you write the necessary code for that (unfortunately that is not provided by the Jetpack team , and neither are Command bindings), and either the View or the Controller can call methods directly on it if necessary. ViewModel is stored across config changes (not across process death, ofc) so it should not hold a direct view reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM