This will be a continuation of the article: The Evolution of MV* Patterns in Android: Part 1 MVVM MVVM is also known as model-view-binder and was created by Microsoft architects Ken Cooper and John Gossman. Google I/O 2017 introduced architecture components that includes and which facilitates developing apps using the MVVM pattern. LiveData ViewModel Android This approach allows you to connect view elements with phenomena and events of the View model. It can be argued that each layer of this pattern does not know about the existence of another layer. The first and main difference is in the names of the business logic layers: in MVP and its derivatives, it is stored in the Presenter, while in MVVM, this role is played by the ViewModel. Secondly, this is the way the View layer and ViewModel interact. This is complicated by the fact that the obviously does not know about the layer, but still controls it. How can this be? More on this a little further. ViewModel View Layers of MVVM pattern are: This layer is responsible for the abstraction of the data sources. Model and ViewModel work together to get and save the data; Model: The purpose of this layer is to inform the ViewModel about the user’s action. This layer observes the ViewModel and does not contain any kind of logic; View: It exposes those data streams which are relevant to the View. Moreover, it serves as a link between the Model and the View; ViewModel: To implement MVVM, you will need to use or Kotlin , which precisely implements the principle of the Observer pattern and is also consistent with the lifecycle of the View. Learn more about working with events: LiveData Flow LiveData occurs simply through callbacks. View knows explicitly and stores a link to the , which allows us to use its methods. Listening to events ViewModel occur through or . We will always have the current value of our specific widget or the entire View layer on the View layer. Changes to the ViewModel MutableLiveData MutableStateFlow Example: ViewModel class MainViewModel : ViewModel() { private val booksRepository: BooksRepository = BooksRepositoryImpl() private val _booksLiveData = MutableLiveData<List<Book>>() val bookLiveData: LiveData<List<Book>> get() = _booksLiveData private val _loadingLiveData = MutableLiveData<Boolean>() val loadingLiveData: LiveData<Boolean> get() = _loadingLiveData fun fetchBooks() { _loadingLiveData.value = true booksRepository.fetchBooks { _booksLiveData.value = it _loadingLiveData.value = false } } } Repository interface BooksRepository { fun fetchBooks(): List<Book> fun saveInFavorites(id: Long): Boolean fun removeFromFavorites(id: Long): Boolean } data class Book(val id: Long, val title: String, val author: String) MainFragment class MainFragment : Fragment(R.layout.fragment_main) { private lateinit var booksRV: RecyclerView private lateinit var progressBar: ProgressBar private val adapter = BooksListAdapter() private val mainViewModel: MainViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) booksRV = view.findViewById(R.id.books_rv) progressBar = view.findViewById(R.id.progress_bar) mainViewModel.fetchBooks() observeLiveData() } private fun observeLiveData() { mainViewModel.loadingLiveData.observe(viewLifecycleOwner) { value -> value?.let { if (it) { progressBar.visibility = View.VISIBLE } else { progressBar.visibility = View.GONE } } } mainViewModel.bookLiveData.observe(viewLifecycleOwner) { value -> value?.let { adapter.submitList(it) } } } companion object { @JvmStatic fun newInstance() = MainFragment() } } In conclusion With the right and experienced approach, MVVM simplifies the process of writing tests for code (due to fewer explicit connections), and it can be a slightly less verbose architecture than MVP and its derivatives.