starring
Room
LiFe cycle
LiveData
ViewModel
Pagination (new)
Slide 5
Slide 5 text
in new suggested architecture
Slide 6
Slide 6 text
in new suggested architecture
Slide 7
Slide 7 text
In architecture components
•A ViewModel provides the data for a specific UI
•The ViewModel does not know about the View!
•Survives configuration change
Slide 8
Slide 8 text
In architecture components
•A ViewModel provides the data for a specific UI
•The ViewModel does not know about the View!
•Survives configuration change
Slide 9
Slide 9 text
In architecture components
•A ViewModel provides the data for a specific UI
•The ViewModel does not know about the View!
•Survives configuration change
Slide 10
Slide 10 text
In architecture components
•A ViewModel provides the data for a specific UI
•The ViewModel does not know about the View!
•Survives configuration change
Slide 11
Slide 11 text
In architecture components
•Remember configuration change can be:
•Rotation
•Any other resize i.e. split screen
•Language change
life cycle: finish
onCreate
onStart
onResume
onPause
onStop
onDestroy
ViewModel
Slide 14
Slide 14 text
How to use
implementation
'android.arch.lifecycle:extensions:1.0.0’
kapt 'android.arch.lifecycle:compiler:1.0.0’
Slide 15
Slide 15 text
How to use
class MyViewModel()
: ViewModel() {
Slide 16
Slide 16 text
How to use
class MyViewModel(app: Application)
: AndroidViewModel(app) {
Slide 17
Slide 17 text
How to use
override fun onCreate(...) {
model = ViewModelProviders
.of(this)
.get(MyViewModel::class.java)
}
Slide 18
Slide 18 text
What if…
constructor arguments needed?
Slide 19
Slide 19 text
How to use
class MyViewModelFactory
:ViewModelProvider.Factory(useCase: MyUseCase) {
fun create(aClass: Class): T {
return MyViewModel(useCase) as T
}
}
Slide 20
Slide 20 text
How to use
ViewModelProviders
.of(this, MyViewModelFactory(usecase))
.get(MyShowsViewModel::class.java)
Slide 21
Slide 21 text
How to use
•Always try to build your own Factory
•Default factory uses newInstance()
which is some hundred times slower
than new calls (reflection)
https://speakerdeck.com/dpreussler/comparing-dependency-injection-
frameworks-and-internals-for-android
Slide 22
Slide 22 text
How to use
•Always try to build your own Factory
•Default factory uses newInstance()
which is some hundred times slower
than new calls (reflection)
https://speakerdeck.com/dpreussler/comparing-dependency-injection-
frameworks-and-internals-for-android
Slide 23
Slide 23 text
How to use
override fun onStopped() {
…
}
No more life cycle forwarding!
Slide 24
Slide 24 text
What if…
I need to clean something when destroyed?
Slide 25
Slide 25 text
What if…
class MyViewModel() : ViewModel() {
override fun onCleared() {
super.onCleared()
cleanupSubscriptions()
}
Slide 26
Slide 26 text
How does
it survive
orientation change?
Slide 27
Slide 27 text
How does it actually work?
class HolderFragment extends Fragment {
public HolderFragment() {
setRetainInstance(true);
}
…
Slide 28
Slide 28 text
How does it actually work?
String HOLDER_TAG =
"android.arch.lifecycle.state.StateProviderH
olderFragment";
Slide 29
Slide 29 text
How does
it know
the activity
is finishing?
Slide 30
Slide 30 text
How does it actually work?
@Override
public void onDestroy() {
super.onDestroy();
mViewModelStore.clear();
}
Slide 31
Slide 31 text
Can I do it differently?
ViewModel is not life cycle aware?
Slide 32
Slide 32 text
It just
refuses to
die
Slide 33
Slide 33 text
remember
Never hold View or Activity references
in the ViewModel!
Slide 34
Slide 34 text
Tell us more
Slide 35
Slide 35 text
What if
Two Fragments
of same Activity
ask for same ViewModel.class via
ViewModelProviders
.of(this)
.get(MyViewModel::class.java)
Slide 36
Slide 36 text
Different ViewModels
RESULT
Slide 37
Slide 37 text
What if
Two Fragments
of same Activity
ask for same ViewModel.class via
ViewModelProviders
.of(this)
.get(MyViewModel::class.java)
Slide 38
Slide 38 text
W
A
I
T
Slide 39
Slide 39 text
result
•Fragment and Activity share the same
FragmentManager
•But implementation uses
Activity’s FragmentManager but
ChildFragmentManager for Fragments
Slide 40
Slide 40 text
result
•Fragment and Activity share the same
FragmentManager
•But implementation uses
Activity’s FragmentManager but
ChildFragmentManager for Fragments
Slide 41
Slide 41 text
What if
Two Fragments
of same Activity
ask for same ViewModel.class via
ViewModelProviders
.of(getActivity())
.get(MyViewMode::class).java
Slide 42
Slide 42 text
result
Same ViewModel
Slide 43
Slide 43 text
Tell us more
Slide 44
Slide 44 text
Other uses cases
communication layer between
activities and fragments
or
fragments and fragments
Slide 45
Slide 45 text
Other uses cases
Replace Loaders
(plus Room and LiveData/Rx)
Slide 46
Slide 46 text
Tell us more
Slide 47
Slide 47 text
ViewModel
like in
Model-View-ViewModel
?
Slide 48
Slide 48 text
Model-View-ViewModel
Slide 49
Slide 49 text
ViewModel in MVVM world
Model
ViewModel
View
View Presenter Model
Slide 50
Slide 50 text
ViewModel in MVVM world
Model
ViewModel
View
View ViewModel Model
Slide 51
Slide 51 text
Is MVP
dead?
Slide 52
Slide 52 text
Is MVP dead?
It’s like Java and Kotlin:
•MVP will stay for quite some time
•There is a new cooler kid in town that won’t
leave
Slide 53
Slide 53 text
Is MVP dead?
It’s like Java and Kotlin:
•MVP will stay for quite some time
•There is a new cooler kid in town that won’t
leave
Slide 54
Slide 54 text
Is MVP dead?
It’s like Java and Kotlin:
•MVP will stay for quite some time
•There is a new cooler kid in town that
won’t leave
Slide 55
Slide 55 text
Is MVP dead?
•Start by putting the ViewModel behind
Presenter
Slide 56
Slide 56 text
Binding to ViewMODELS
Activity
Activity
ViewModel
(un)bind
(un)bind
Slide 57
Slide 57 text
IntroduciNG LIVE DATA
Activity
Activity
LiveData
LiveData
ViewModel
Slide 58
Slide 58 text
IntroduciNG LIVE DATA
•Observable similar to RxJava
•Life cycle aware
•Doesn’t emit when not needed
•Memory leaks save
Slide 59
Slide 59 text
IntroduciNG LIVE DATA
class MyViewModel(): ViewModel() {
val message =
MutableLiveData()
Slide 60
Slide 60 text
IntroduciNG LIVE DATA
myModel.message.observe(
this,
Observer { display(it) })
Slide 61
Slide 61 text
Is there
something
better?
Slide 62
Slide 62 text
Databinding!
Slide 63
Slide 63 text
Data binding full picture
XML ViewModel
bind
Slide 64
Slide 64 text
Solves the one big android
question once and forever
who is the view?
Slide 65
Slide 65 text
ViewModel in data binding
Slide 66
Slide 66 text
ViewModel in data binding
Slide 67
Slide 67 text
How to use
class AllShowsViewModel: ViewModelObservable() {
var title : CharSequence = ""
Slide 68
Slide 68 text
How to use
class AllShowsViewModel: ViewModelObservable() {
@Bindable
var title : CharSequence = ""
private set(value) {
if (field != value) {
field = value
notifyPropertyChanged(BR.title)
}
}
Slide 69
Slide 69 text
How to use
class AllShowsViewModel: ViewModelObservable() {
@Bindable
var title by bindable("")
private set
Custom property delegate
Slide 70
Slide 70 text
How to use
class AllShowsFragment : Fragment () {
@Inject
lateinit var showsViewModel: AllShowsViewModel
Slide 71
Slide 71 text
How to use
class AllShowsFragment : Fragment () {
@Inject
lateinit var showsViewModel: AllShowsViewModel
override fun onCreateView(…):View? =
Slide 72
Slide 72 text
How to use
class AllShowsFragment : Fragment () {
@Inject
lateinit var showsViewModel: AllShowsViewModel
override fun onCreateView(…):View? =
FragmentShowsBinding.inflate(
inflater, container, false).apply {
viewModel = showsViewModel
}).root
Slide 73
Slide 73 text
How to use
class AllShowsFragment : Fragment () {
@Inject
lateinit var showsViewModel: AllShowsViewModel
override fun onCreateView(…):View? =
FragmentShowsBinding.inflate(
inflater, container, false).apply {
viewModel = showsViewModel
}).root
fragment_shows.xml
Slide 74
Slide 74 text
How to use
class MyViewModel()
:ViewModelObservable() {
Coming soon
Jose Alcérreca, Google
https://medium.com/@dpreussler/add-the-new-viewmodel-to-your-mvvm-36bfea86b159
Slide 75
Slide 75 text
How do I…
Slide 76
Slide 76 text
.. show a toast
class SeriesViewModel : Viewmodel() {
…
@Bindable
var error = ObservableField()
Slide 77
Slide 77 text
.. show a toast
viewModel.error.addOnPropertyChangedCallback(
object : OnPropertyChangedCallback() {
override fun onPropertyChanged(…) {
showToast(viewModel.error.get()
}
})
Slide 78
Slide 78 text
.. show a toast (alternative)
@BindingAdapter("showError")
fun ViewGroup.onErrorAppeared(error: String?){
errorString?.let {
showToast(context, error))
}
}
Slide 79
Slide 79 text
Data binding full picture
XML
Activity ViewModel
(un)bind
bind
Life cycle
aware class (un)bind
Slide 80
Slide 80 text
WAYS TO OBSERVE DATA from VM?
•Data binding Observable
from xml or code, might need unregister
•RxJava Observable
from code, needs unregister
•LiveData Observable,
from code, no unregister, life cycle aware
Slide 81
Slide 81 text
let`s sum up
•Architecture components are
here
•Use the parts you need
•Goal: common architecture
language
•Databinding rocks
•Know about life cycle
Slide 82
Slide 82 text
Want to know more
• https://medium.com/@dpreussler/add-the-new-
viewmodel-to-your-mvvm-36bfea86b159
• https://proandroiddev.com/customizing-the-new-
viewmodel-cf28b8a7c5fc
• http://hannesdorfmann.com/android/arch-components-
purist
• https://blog.stylingandroid.com/architecture-components-
viewmodel/
• https://www.youtube.com/watch?v=QrbhPcbZv0I
• https://www.youtube.com/watch?v=c9-057jC1ZA
Slide 83
Slide 83 text
Southpark copyright
Disclaimer
Slide 84
Slide 84 text
viacom.tech
Slide 85
Slide 85 text
View Model
IN
ACTION
@PreusslerBerlin
Slide 86
Slide 86 text
Does that mean
all problems are solved?
Slide 87
Slide 87 text
all problems solved?
ViewModels provide a convenient way to
retain data across configuration changes
but they are not persisted if the application
is killed by the operating system
https://developer.android.com/topic/libraries/architecture/viewmodel.html#viewm
odel_vs_savedinstancestate
Slide 88
Slide 88 text
but but
WHY?
Slide 89
Slide 89 text
Why?
The data saved via onSaveInstanceState is kept in
the system process memory
and the Android OS allows you to keep only a very
small amount of data
so it is not a good place to keep actual data for
your app.
TransactionTooLargeException anyone?
Slide 90
Slide 90 text
MeaNS
ViewModels gives us rotation
But takes away recreation
Slide 91
Slide 91 text
after The truth
•Keep non-UI states in non-UI layer
Not in bundle!
•Use real caching strategies
•Allows updating cache in background
Slide 92
Slide 92 text
after The truth
•Keep non-UI states in non-UI layer
Not in bundle!
•Use real caching strategies
•Allows updating cache in background
Slide 93
Slide 93 text
after The truth
•Keep non-UI states in non-UI layer
Not in bundle!
•Use real caching strategies
•Allows updating cache in background
Slide 94
Slide 94 text
but but
EditText might have restored it’s state
but the ViewModel will not now about it
Slide 95
Slide 95 text
but but
Where to store the UI state?
Slide 96
Slide 96 text
store the UI state
In Bundles!
Slide 97
Slide 97 text
but but
Who owns the UI state?
Slide 98
Slide 98 text
store the UI state
The ViewModel
Slide 99
Slide 99 text
store the UI state
Slide 100
Slide 100 text
lets tweak it
class MyModelFactory(val bundle: Bundle?)
:ViewModelProvider.Factory() {
…
fun create(aClass: Class): T {
return MyViewModel().apply {
readFrom(bundle)
} as T
}
...
Slide 101
Slide 101 text
lets tweak it
override onSaveInstanceState(bundle: Bundle){
super.onSaveInstanceState(bundle);
viewModel.writeTo(bundle);
}