RxJava instead of LiveData in MVVM
It’s been a while that I use BehaviorProcessor
s of RxJava
as io.reactivex.rxjava2
instead of LiveData
in android.arch.lifecycle
. For instance, you can find a class named RxLifecycleHandler
in CleanArchitecture, and its usage in the BaseFragment
and AlbumFragment
is like the following.
The observe
extension function just passes handling of subscriptions to the RxLifecycleHandler
instance. Then RxLifecycleHandler
subscribes when the fragment is between onStart
and onStop
callbacks, otherwise it disposes. Despite I’m doing it for a while successfully, there are little people that are aware of it, so I decided to publish this article. Although, before this I thought it’s a simple idea and not worth writing, but now I think this should be the exact reason to publish it!
LiveData was deprecated
So, what is the advantage of using RxJava
streams instead of LiveData
?
— First of all, LiveData
has just one strategy on backpressure, which is dropping, so the values are missing out if you post
them fast into LiveData
.
— Second, LiveData
has only one strategy to hold the values, but we have PublishProcessor
, BehaviorProcessor
, ReplayProcessor
, and etc. Or if you’re working in the main thread all the time, so have no plan to support backpressure, you can use PublishSubject
, BehaviorSubject
, ReplaySubject
, and etc.
— Third, while you test LiveData
you miss some RxJava testing sugars, such as TestObserver
, TestScheduler
etc.
So at least there is three disadvantages of using LiveData
. But if it’s so, why we use it? Because it understands the lifecycle of Activities and Fragments in the Android framework. As you can see in the code in CleanArchitucture project, that I mentioned before, supporting such behavior is not so hard, so I made a library to handle this lifecycle. You can use it as simple as adding the dependency to your project as following. Remember that we assume here we need the emitted values just after onStart
callback and before onStop
.
implementation "com.github.hadilq:rxlifecyclehandler:0.1.0"
Also you can find the source code in the below link.
The same goal can be achieved by Flow
implementation of Kotlin Coroutines, so I also implemented the following library for this purpose, but let’s talk about it later.
implementation "com.github.hadilq:coroutinelifecyclehandler:0.1.0"
Where you can find its source code in the below link.
RxJava
To make your life easier, as an example of ViewModel
in MVVM
architectural pattern, let me copy some parts of the code in CleanArchitectureFP project which is using processors instead of LiveData
.
In the above example you can see openAlbumDetailsLiveEvent
, which as its name is showing, is a LiveEvent
that means the ViewModel
would not hold the emitted values, because of PublishProcessor
implementation, but in case of networkErrorLiveData
you can see after emitting a value the data would be held in the BehaviorProcessor
just the same as what LiveData
would do, which means, in case of configuration change the value would be passed to the new Activity or fragment. Imagine you could find a use-case for ReplayProcessor
and others.
Notice
If you want to commit a fragment after receiving an event over the above method, you may need to use commitAllowingStateLoss
method as the Google document mentioned, the onSaveInstanceState
method may called before onStop
callback in pre-Build.VERSION_CODES.P
Androids. Also I have a plan to provide more solution to this.
Hope you use it and have some feedback for me. Also if you have any other ideas, please don’t forget to share with me. You can find me on Tweeter and LinkedIn …
Update
You can find the improve of solution for above problem in my next article https://medium.com/@hadilq.dev/save-state-by-using-rxjava-or-kotlin-flow-526f6d282b84. Enjoy!