Lesson 04 Flow ‐ MVVM Pattern, First approach to Flow, and Asynchronous Operations - FranGarc/LearningPath GitHub Wiki

Topic: MVVM Pattern, First approach to Flow, and Asynchronous Operations.

MVVM is a presentation pattern, a way to organize the code. It stands for Model (data information), View (UI), ViewModel. Following the SOLID principles, it advocates for code separation: UI shouldn't have logic code in it.

In order to separate the UI code from the logic code, we'll refactor said logic code into viewmodels. We'll use StateFlows to communicate state information between the viewmodel and the screen.

After that, we'll start working with data access as suspend functions, since that's the way: no matter where your data comes from (remote API, local database, DataStore), accesing it it's always done asynchronously to avoid blocking the UI thread. This is done through the use of coroutines.

Task: Refactor Logic.

Modify our MockDataSource current functions' signature to make them suspend functions. They must return a Flow of the they were returning before (PokemonList / PokemonDetail). Add it a delay of at least 1000 (1 second) to simulate loading times.

Requisites

Each screen will have its own ViewModel. Each viewmodel will have a stateflow to transmit the information (list of pokemon, detail data) to the respective screen. Said stateflow will collect the information from the DataSource flow. Each screen will be observing said stateflow.

Each ViewModel will need to instantiate a MockDataSource object.

Up until now, our Screens used to call directly to MockDataSource for the data, now they'll have to get it from their respective ViewModel. Since it will be a suspend function, view (Screen) will need to use a CoroutineScope with an IO dispatcher.

The ViewModel will get the data from the DataSource.

At this moment, we won't move the navigation logic.

Tips & Advice.

You may want to change one MockDataSource function at a time so you can test everything goes ok without having to tackle the next step's errors.

Also, changing the MockDataSource functions to suspend will disrupt your previews, remove them for the moment being.

It's good practices to have a pair of public/private variables for each state. The private one will be the mutable state: only the viewModel can change its value. The public one is merely a non mutable copy so that nothing in the screen code can change its value.

MutableStateFlows need to be initialized inmediately with some value. This is not a problem for lists, but it can be for single objects (like PokemonDetail). For the moment, we'll use an ugly hack by giving the PokemonDetail dataclass default values we can use to prevent its screen from rendering until the actual data has arrived.

Research terms.

  • MVVM
  • ViewModel
  • Coroutines
  • CoroutineScope
  • Dispatchers
  • ViewModelScope
  • Flow
  • StateFlow
  • emit
  • collect

Additional resources.

⚠️ **GitHub.com Fallback** ⚠️