5. Mvvm
Part 1
• Design pattern
• Separation of concerns
• Components
• Communication
• Multiple definitions
6. Model - View - ViewModel
Holds Ui data, and exposes it via event / data streams (RX)
Abstracts the data source
Mvvm
7. Mvvm
Model - View - ViewModel
observes data from the viewModel
Display data
Delegates user actions to the viewModel
Dumb - No logic allowed!
8. Mvvm
Model - View - ViewModel
Holds ready to consume data, and exposes it to the consumer
Does not care who consumes its data.
Get user actions from view, and applies domain logic
9. View ViewModel Model
•ViewModel does not know the view/consumer of the data
•It encourages event driven/reactive programming
•View notify the viewModel about events
•Many to one relationship
10. •ViewModel does not know the view/consumer of the data
•It encourages event driven/reactive programming
•View notify the viewModel about events
•Many to one relationship
View ViewModel Model
11. •ViewModel does not know the view/consumer of the data
•It encourages event driven/reactive programming
•View notifies the viewModel about events
•Many to one relationship
View ViewModel Model
12. •ViewModel does not know the view/consumer of the data
•It encourages event driven/reactive programming
•View notify the viewModel about events
•Many to one relationship
View ViewModel Model
13. • Separation of concerns
• Clear and concise
• Communication
• Multiple definitions
This is the MVVM pattern
21. LifeCycle
Holds the information about the lifecycle state of a component and
allows other objects to observe this state
We could approach this set of EVENTS and STATES as a
graph data structure.
38. class MyAmazingObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun startDoSomething() {
//bla bla
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun stopDoSomething() {
//bla bla
}
}
LifeCycleObserver
39. class MyAmazingObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun startDoSomething() {
//bla bla
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun stopDoSomething() {
//bla bla
}
}
lifecycle.addObserver(MyAmazingObserver())
LifeCycleObserver
40. class MyAmazingObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun startDoSomething() {
lifeCycle.currentState.isAtLeast(Resumed)
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun stopDoSomething() {
//bla bla
}
}
lifecycle.addObserver(MyAmazingObserver())
LifeCycleObserver
41. LiveData
liveData, is a data holder class, which is lifeCycle aware.
It holds values, and allow them to be observed.
Emit events only if the observer is active!
42. Observer of LiveData is ACTIVE, if its Lifecycle.State is STARTED/
RESUMED. Otherwise, its considered as INACTIVE
val liveData : LiveData<String> = …
liveData.observe(this, Observer {
//bla bla
})
LiveData is LifeCycleAware
If observer will be destroyed - it will be removed
When LifeCycleOwner will return to ACTIVE state - it will be updated
43. MutableLiveData - update liveData objects
class MainViewModel : ViewModel() {
private val username = MutableLiveData<String>()
val userName: LiveData<String> get() = _username
fun updateUserNameMainThread() {
username.value = "Or Main Thread" // kotlin's setValue()
}
fun updateUserNameBackgroundThread() {
username.postValue("Or Background Thread!")
}
}
LiveData is immutable.
44. MediatorLiveData
Combining multiple LiveDataSources
private val networkErrors: LiveData<String> = ...
private val userUpdates: LiveData<User> = ...
val displayMessage = MediatorLiveData<String>()
displayMessage.addSource(userUpdates) { user ->
displayMessage.postValue("User ${user.name} added")
}
displayMessage.addSource(networkErrors) { errorMessage ->
displayMessage.postValue("Error $errorMessage")
}
45. Transformations.Map
Maybe we want to apply some FUNCTION on each emission.
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> =
Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
46. Transformations.Map
Maybe we want to apply some FUNCTION on each emission.
This function, would be calculated on UI thread, in a lazy way
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> =
Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
47. LiveData
• Ensures your UI matches your data state
• No memory leaks
• No crashes due to stopped activities
• No more manual lifeCycle handling
• Always up to date data
• Proper configuration changes
48. LifeCycle Aware - super power!
Survive configuration changes - super power!
Store and manage UI related data
Android’s ViewModel
58. • swipe away from multitask view
• Navigate back
• Explicit call to finish()
More death options
The user will not expect the ui to restore it’s state after they
have occurred.
59. Mvvm using Android architecture components
• Survive configuration changes
• LifeCycle aware
• Separation of concerns
• Reactive