This Sample aim to understand the concepts of two main Jetpack components - ViewModel and LiveData with Kotlin as Programming language. Please read the ReadMe file for the theoretical description.
1. ViewModel is a class responsible for preparing and managing data to UI components(Activity or fragments) and also survives in orientation changes.
2. It remains alive until its reference scope is alive.
3. It should never access your view hierarchy or hold any reference of UI.
4. It was announced in google IO 2017.
5. Another important use of ViewModel is that it pcan be used a communication layer between different fragments of activity so that they nether need to talk to other fragment directly.
6. OnCleared() method is last method called inside ViewModel before its destruction.Useful if you want to clear some references in order to prevent memory leak.
7. If you want context inside your Viewmodel then use AndroidViewModel inside it as it have default application context inside it.
* Disadvantage of ViewModel over SavedInstanceState is It do not survice on process kill due to low memory but SavedInstanceState does.
Create a class and Extends a ViewModel class inside it.
class MainViewModel : ViewModel() {
}
Create a ViewModelProvider instance inside your UI referencing that class which extends ViewModel class.Earlier it was ViewModelProviders but it is deprecated now.
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
An utility class that provides ViewModel for a scope.
ViewModelProvider.Factory is use to create a custom constructor inside ViewModel.
class MyViewModelFactory(val arg:Int) :ViewModelProvider.Factory { override fun create(modelClass: Class): T { return modelClass.getConstructor(Int::class.java).newInstance(arg) } }
mainViewModel = ViewModelProvider(this,MyViewModelFactory(20)).get(MainViewModel::class.java)
When you write ViewModelProvider(this).get(MainViewModel::class.java) then ViewModelProvider map the ViewModel instance with "this" referencing UI component. For the first time it creates an instance of ViewModel then when you rotate the device then it uses the same instance of ViewModel a Singleton pattern is internally used for saving the state of ViewModel.
It is an observable Data holder class. Its Lifecycle aware.
Its instance is created inside the ViewModel class and Observer inside the UI(Activity or fraagment).
It only trigger on Active UI thus saving you from OutOfMemory and UI related crashes.
1. Map() - apply function to output of A liveData and send Result to LiveData B.
2. SwitchMap() - apply function that swaps LiveData observer is listening to.
3. MediatorLiveData - It is subclass of liveData.LiveData without mmultiple sources for custom transformation.
* Both Map() and SwitchMap() returns MediatorLiveData object.
<************************** Internal Implementation of Map and SwitchMap *********************>
@MainThread
public static LiveData map(@NonNull LiveData source,
@NonNull final Function func) {
final MediatorLiveData result = new MediatorLiveData<>();
result.addSource(source, new Observer() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(func.apply(x));
}
});
return result;
}
@MainThread
public static LiveData switchMap(@NonNull LiveData trigger,
@NonNull final Function> func) {
final MediatorLiveData result = new MediatorLiveData<>();
result.addSource(trigger, new Observer() {
LiveData mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}