I'm adopting MVVM to my Android apps recently. In order to solve the problems underlying with the lifecycle of an app, Google had released LiveData.
The usage of LiveData has different scenarios, as pointed out in the medium article wrote by Jose Alcérreca, you can use SingleLiveEvent or something like the event wrapper pattern.
I want to make sure the SingleLiveEvent, or the event wrapper pattern, which one would be the best practice to use with LiveData in Android MVVM architecture. And I found the Google I/O app of this year(2018) have no usages of SingleLiveEvent, it uses event wrapper pattern instead.
Previously I have opened an issue on the project android-architecture, at first I'm seeking an official reply, but it seems to have no comments at all. As a result, I would like to hear the advice from the developers who already use these stuff and have reflections on it.
Please share your precious experiences, thank you in advance.
SingleLiveEvent is a subclass of MutableLiveData with a single Observer Observing it at a time, hence it is aware of view's lifecycle.
StateFlow and LiveData have similarities. Both are observable data holder classes, and both follow a similar pattern when used in your app architecture. The StateFlow and LiveData do behave differently: StateFlow requires an initial state to be passed into the constructor, while LiveData does not.
All observers will only receive events once they happen! Next use it just as you would regular live data: Multiple observers receive events. In case of same multiple observer problem(fragment back-stack) it is possible to use observeInOnStart() method.
LiveData is a wrapper that can be used with any data, including objects that implement Collections , such as List . A LiveData object is usually stored within a ViewModel object and is accessed via a getter method, as demonstrated in the following example: Kotlin Java.
I'm not a fan of SingleLiveEvent
because it restricted to one observer but you can add many observers as well, so it can be error-prone.
But in a very simple scenario(like the todo app that you mentioned), it can be a better option than event wrapper pattern.
In a complex scenario, event wrapper pattern would be a better option, but it also has some limitations. This implementation assumes you only have one main consumer (see getContentIfNotHandled
). So, I think dealing with multiple observers will cause boilerplate to decide which one is the main consumer or when I should call getContentIfNotHandled
or peekContent
.
But, All these limitations can be fixed with your own implementation.
For example here is an extended version of SingleLiveEvent
that supports multiple observers:
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private LiveData<T> liveDataToObserve;
private final AtomicBoolean mPending = new AtomicBoolean(false);
public SingleLiveEvent() {
final MediatorLiveData<T> outputLiveData = new MediatorLiveData<>();
outputLiveData.addSource(this, currentValue -> {
outputLiveData.setValue(currentValue);
mPending.set(false);
});
liveDataToObserve = outputLiveData;
}
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
liveDataToObserve.observe(owner, t -> {
if(mPending.get()) {
observer.onChanged(t);
}
});
}
@MainThread
public void setValue(T value) {
mPending.set(true);
super.setValue(value);
}
}
As you see, It's not about SingleLiveEvent
vs event wrapper pattern, It all depends. Personally, I use other patterns (like patterns existing in React/Flux world) for dealing with states.
Keep in mind that there is no silver bullet in software engineering.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With