Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MVVM on Android - Berlindroid

MVVM on Android - Berlindroid

MVVM is a design pattern for architecting applications that have become popular on Android.

In this talk, we will look at what is MVVM and how to use ArchitectureComponents with them, and share my experience on how I build robust, maintainable and testable apps using them.

- What is MVVM
- How it differs from other design patterns
- Learn how to do MVVM with Architecture Components
- A brief look at testing
- Advantages

Akshay Chordiya

April 24, 2019
Tweet

More Decks by Akshay Chordiya

Other Decks in Programming

Transcript

  1. 3 MV* Model represents data, and business logic View presents

    information that it retrieves from one or more model objects Model View
  2. 4 MVVM Model represents data, and business logic View presents

    information that it observes from one or more ViewModel objects Model View ViewModel Interacts with model and on change notifies the view to update User Action Observes Request data Expose data
  3. Lifecycle LifecycleObserver [e.g. LiveData] LifecycleOwner [Activity / Fragment] LifecycleOwners are

    ViewController with their own lifecycle LifecycleObserver observe LifecycleOwners and are notified about lifecycle changes
  4. 13 class AnalyticsObserver : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun trackOpenEvent() {

    Timber.d(“onCreate: Send open event") } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun trackCloseEvent() { Timber.d(“onDestroy: Send close event”) } }
  5. 17 LiveData value updates Observe for updates Is STARTED or

    RESUMED? Notify the observer Update the UI
  6. 19

  7. 22 class CounterViewModel : ViewModel() { var counter: MutableLiveData<Int> =

    MutableLiveData() init { counter.value = 0 } } Emits data
  8. 23 class CounterViewModel : ViewModel() { var counter: MutableLiveData<Int> =

    MutableLiveData() init { counter.value = 0 } fun increment() { counter.value = counter.value?.inc() } } Emits data Emits data
  9. 24 // Get the ViewModel in [Activity, Fragment] val counterViewModel

    = ViewModelProviders.of(this) .get(CounterViewModel::class.java)
  10. 25 // Get the ViewModel in [Activity, Fragment] val counterViewModel

    = ViewModelProviders.of(this) .get(CounterViewModel::class.java) // Observe the `LiveData` for changes counterViewModel.counter.observe(this, Observer { count.text = counterViewModel.counter.toString() })
  11. 26 // Get the ViewModel in [Activity, Fragment] val counterViewModel

    = ViewModelProviders.of(this) .get(CounterViewModel::class.java) // Observe the `LiveData` for changes counterViewModel.counter.observe(this, Observer { count.text = counterViewModel.counter.toString() }) // Increment the count increment.setOnClickListener { counterViewModel.increment() }
  12. onCleared() ViewModel Scope Activity created Activity rotated finish() Finished onCreate

    onStart onResume onPause onStop onCreate onDestroy onStart onResume onPause onStop onDestroy
  13. onCleared() Activity created Activity rotated finish() Finished onCreate onStart onStop

    onCreate onDestroy onStart onResume onPause onStop onDestroy 0 0 1 1 2 onPause onResume 3 3
  14. 36 override fun onCreate(savedInstanceState: Bundle?) { // ... // Get

    ID val id = savedInstanceState?.getInt("id", 0) viewModel.setId(id) // Observe the data from ViewModel viewModel.getData().observe(...) } override fun onSaveInstanceState(outState: Bundle?) { outState?.putInt("id", someId) super.onSaveInstanceState(outState) }
  15. 37 override fun onCreate(savedInstanceState: Bundle?) { // ... // Get

    the ViewModel in [Activity, Fragment] val detailViewModel = ViewModelProviders.of( this, SavedStateVMFactory(this) ).get(DetailViewModel::class.java) }
  16. 38 override fun onCreate(savedInstanceState: Bundle?) { // ... // Get

    the ViewModel in [Activity, Fragment] val detailViewModel = ViewModelProviders.of( this, SavedStateVMFactory(this) ).get(DetailViewModel::class.java) // Get ID viewModel.setId(id) // Observe the data from ViewModel viewModel.getData().observe(...) }
  17. 39 class DetailViewModel( private val savedState: SavedStateHandle ) : ViewModel()

    { fun getData(): LiveData<Data> = // Restore data fun setId(id: Int) { // Save id savedState.set("id", id) } }
  18. 41 UI Controller [Activity / Fragment] ViewModel Repository Model Remote

    Data Source SQLite webservice All things related to View like rendering Holds data required by UI
  19. 42 UI Controller [Activity / Fragment] Repository Model Remote Data

    Source SQLite webservice ViewModel LiveData LiveData LiveData Room Retrofit
  20. Testing Component Tests Mock UI Espresso ViewModel ViewModel JUnit Repository

    Repository JUnit DAO and WebService DAO Instrumented - WebService Instrumented MockWebServer