简体   繁体   中英

confusion for view's and viewmodel's responsibility in mvvm architecture

i asked this some days ago here but didn't get any answer

i have a confusion about what code should be placed in view and what in viewmodel

for example click events

here is a snippet code of google ToDo app example for showing application architecture ( Link ):

//this code is placed in view (TasksFragment)
override fun onOptionsItemSelected(item: MenuItem) =
        when (item.itemId) {
            R.id.menu_clear -> {
                viewModel.clearCompletedTasks()
                true
            }
            R.id.menu_filter -> {
                showFilteringPopUpMenu()
                true
            }
            R.id.menu_refresh -> {
                viewModel.loadTasks(true)
                true
            }
            else -> false
        }

private fun showFilteringPopUpMenu() {
    val view = activity?.findViewById<View>(R.id.menu_filter) ?: return
    PopupMenu(requireContext(), view).run {
        menuInflater.inflate(R.menu.filter_tasks, menu)

    setOnMenuItemClickListener {
        viewModel.setFiltering(
            when (it.itemId) {
                R.id.active -> TasksFilterType.ACTIVE_TASKS
                R.id.completed -> TasksFilterType.COMPLETED_TASKS
                else -> TasksFilterType.ALL_TASKS
            }
        )
        viewModel.loadTasks(false)
        true
    }
    show()
  }
}

as you can see there are 3 three items for a menu

2 of them delegated to viewmodel and one handled in view

beside that there are some logic in view that make decision based on view's id, but in mvvm definition said there must be no condition in view

Is really easy. It depends, every architecture question is not written in golden characters. But there are some best practices that should be followed. You want to maintain your classes short, readable and most important testable. Moving your business logic to the view model is really important, because then you can test your viewModel with Junit tests without mocking specific Android components.

The when you mention is in some way business logic but the it.itemId you see is really dependent by the view and is under the scope of the run command, moving into the viewmodel as parameter of the function setFiltering would be opinable for few developers

Even advanced Clean Architecture models could have and they actually have the status that is showed with a when, for instance

 private fun handleDataState(resource: Resource<List<ProjectView>>) {
        when (resource.status) {
            ResourceState.SUCCESS -> {
                progress.visibility = View.GONE
                recycler_projects.visibility = View.VISIBLE
                resource.data?.let {
                    adapter.projects = it.map { mapper.mapToView(it) }
                    adapter.notifyDataSetChanged()
                }
            }
            ResourceState.LOADING -> {
                progress.visibility = View.VISIBLE
                recycler_projects.visibility = View.GONE
            }
        }
    }

EDIT

the first function viewModel.clearCompletedTasks() is delegated to the view model because you are going to clear the cache in (usually)a repository layer, in other words you are eliciting what is called an use case, delegating this so called business logic outside the view that is popular today to make it "as dumb as possible", you do not want that the view clear the tasks, but want that the underlyer object that represents the tasks is cleared, and only then is showed in the view as status.

The same is for the third viewModel.loadTasks(false) this is an use case as well and furthermore you are also passing a boolean, that is going to be injected into the viewModel, or even beyond if you use clear architecture. The rule of thumb is the view should have view components, the business logic should stay in the view model. This is a good starting point, but please be aware that the MVVM can be applied to other types of more complex architectures.

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