229

I am not getting the reason to use RxJava in Android and LiveData from Android Architectural Components.It would be really helpful if the usecases and differences between the both are explained along with sample example in the form of code which explains the differences between the both.

Scott Merritt
  • 1,284
  • 2
  • 13
  • 24
rahul66
  • 2,413
  • 2
  • 14
  • 8

11 Answers11

144

Regarding the original question, both RxJava and LiveData complement each other really well.

LiveData shines on ViewModel layer, with its tight integration with Android lifecycles and ViewModel. RxJava provides more capabilities in transformations (as mentioned by @Bob Dalgleish).

Currently, we're using RxJava in data source and repository layers, and it's transformed into LiveData (using LiveDataReactiveStreams) in ViewModels (before exposing data to activities/fragments) - quite happy with this approach.

kzotin
  • 5,365
  • 3
  • 29
  • 36
  • 11
    If we understood you correctly, then LiveData is only useful for Android UI-specific implementations. If we are just building a generic app with Clean Architecture, and sharing this architecture with other platforms, then RxJava is a better fit than LiveData? – IgorGanapolsky May 16 '18 at 14:30
  • 1
    @IgorGanapolsky what language/frameworks do you use for generic app? – kzotin May 24 '18 at 16:14
  • Android-independent APIs and Clean Arch written in Java/Kotlin. – IgorGanapolsky May 24 '18 at 16:37
  • 4
    can you suggest any working example of LiveDataReactiveStreams in your answer? – Pawan May 30 '18 at 21:16
  • e.g. following extension function converts Flowable into LiveData: `LiveDataReactiveStreams.fromPublisher(this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()))` – kzotin May 31 '18 at 09:35
  • 3
    @kzotin you don't need that `observeOn`, `LiveDataReactiveStreams` does that anyway by calling `LiveData.postValue()`. And there's no guarantee your `subscribeOn` will have any effect in general. – arekolek Jun 21 '18 at 11:36
  • The LiveData also can be used with Room and repository too, not only with viewmodel layer, see the doc : https://developer.android.com/topic/libraries/architecture/livedata#use_livedata_with_room . There are many codelabs that show how to uses the LiveData with this components. See this codelab: https://codelabs.developers.google.com/codelabs/advanced-kotlin-coroutines/index.html#0 – Leonardo Costa Dec 20 '19 at 11:24
  • 2
    I found this great article on big nerd ranch [Where RxJava meets LiveData](https://www.bignerdranch.com/blog/livedatareactivestreams-where-rxjava-meets-livedata/) – Mohammad Reza Khahani May 03 '20 at 17:09
  • I posted a complete solution interfacing LiveData with RxJava and Retrofit using a slightly modified version of LiveDataReactiveStreams in this thread: https://stackoverflow.com/a/62057939 – Lee Hounshell Jun 02 '20 at 18:38
  • You can use coroutines and get rid of the hustle the RX creates. – Shivansh Nov 11 '20 at 14:10
134

Android LiveData is a variant of the original observer pattern, with the addition of active/inactive transitions. As such, it is very restrictive in its scope.

Using the example described in Android LiveData, a class is created to monitor location data, and register and unregister based on application state.

RxJava provides operators that are much more generalized. Let's assume that this observable will provide location data:

Observable<LocationData> locationObservable;

The implementation of the observable can be built up using Observable.create() to map the call back operations. When the observable is subscribed, the call back is registered, and when it is unsubscribed, the call back is unregistered. The implementation looks very similar to the code provided in the example.

Let's also assume that you have an observable that emits true when the application is active:

Observable<Boolean> isActive;

Then you can provide all the functionality of LiveData by the following

Observable<LocationData> liveLocation =
  isActive
    .switchMap( active -> active ? locationObservable : Observable.never() );

The switchMap() operator will either provide the current location as a stream, or nothing if the application is not active. Once you have the liveLocation observable, there a lot of things you can do with it using RxJava operators. My favorite example is:

liveLocation.distinctUntilChanged()
  .filter( location -> isLocationInAreaOfInterest( location ) )
  .subscribe( location -> doSomethingWithNewLocation( location ) );

That will only perform the action when the location changed, and the location is interesting. You can create similar operations that combine time operators to determine speed. More importantly, you can provide detailed control of whether operations happen in the main thread, or a background thread, or a multiple threads, using RxJava operators.

The point of RxJava is that it combines control and timing into a single universe, using operations provided from the library, or even custom operations that you provide.

LiveData addresses only one small part of that universe, the equivalent of building the liveLocation.

Bob Dalgleish
  • 8,167
  • 4
  • 32
  • 42
  • 2
    Thanks, the LiveData docs don't seem to reference a location sample anymore. There are more interesting points (with a location sample) here: http://androidkt.com/livedata/ – Daniel Wilson Dec 18 '17 at 18:04
  • 5
    @DanielWilson the link is not available anymore. – Tura Oct 03 '18 at 10:16
  • 1
    Dude I can't remember wtf was on that link :D I like Mark Allison's sample code for a live data: https://blog.stylingandroid.com/architecture-components-livedata/ – Daniel Wilson Oct 03 '18 at 10:24
  • 4
    `The point of RxJava is that it combines control and timing into a single universe, using operations provided from the library, or even custom operations that you provide.` But isn't LiveData lifecycle aware. If we were to use Rx, wouldn't we have to handle the lifecycle changes? – Sparker0i Nov 11 '18 at 07:30
  • @Sparker0i got point here. RxJava is not lifecycle aware. we have to handle manually. where as in LiveData it is already taken care of lifecycle. – Aks4125 Dec 14 '18 at 07:23
  • We can pass LiveData to another thread for example network call and then that thread can postValue in the livedata which subscriber can listen to. It also take care of Lifecycle. I believe RxJava should be used only if you have more complex cases. – Hitesh Bisht Jun 22 '19 at 15:31
  • You can achieve everything you mentioned above by mixing it up with Kotlin features. Admit that RX is now irrelevant for most use cases. – Shivansh Nov 11 '20 at 14:08
  • Kotlin's implementation of RxJava is quite good, I understand. However, co-routines and streams are not a replacement for RxJava, as it cannot handle the space-time-space multiplexing inherent in reactive extensions. – Bob Dalgleish Nov 17 '20 at 21:32
123

There are many differences between LiveData and RxJava:

  1. LiveData is not a STREAM while in RxJava everything (literally everything) is a STREAM.
  2. LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
  3. LiveData is synchronous, So you can't execute a chunk of code (network call, database manipulation etc.) asynchronously using just LiveData as you do with RxJava.
  4. What best you can do to exploit the most of this duo is to use RxJava for your business logic (network call, data manipulation etc, anything that happens in and beyond Repository) and use LiveData for your presentation layer. By this, you get transformation and stream capabilities for your business logic and lifecycle-aware operation for your UI.
  5. LiveData and RxJava compliment each other if used together. What I mean is, do everything with RxJava and at the end when you want to update UI, do something like the code given below to change your Observable into LiveData. So, your View (UI) observes to the LiveData in ViewModel where your LiveData is nothing but non-mutable MutableLiveData (or MutableLiveData is mutable LiveData).
  6. So the question here is, why should you even use LiveData at the first place? As you can see below in the code, you store your response from RxJava to MutableLiveData (or LiveData) and your LiveData is lifecycle-aware, so in a way, your data is lifecycle-aware. Now, just imagine the possibility when your data itself know when and when-not-to update the UI.
  7. LiveData doesn't have a history (just the current state). Hence, you shouldn't use LiveData for a chat application.
  8. When you use LiveData with RxJava you don't need stuff like MediatorLiveData, SwitchMap etc. They are stream control tools and RxJava is better at that by many times.
  9. See LiveData as a data holder thing and nothing else. We can also say LiveData is lifecycle-aware consumer.

    public class RegistrationViewModel extends ViewModel {
        Disposable disposable;

        private RegistrationRepo registrationRepo;
        private MutableLiveData<RegistrationResponse> modelMutableLiveData =
                new MutableLiveData<>();

        public RegistrationViewModel() {
        }

        public RegistrationViewModel(RegistrationRepo registrationRepo) {
            this.registrationRepo = registrationRepo;
        }

        public void init(RegistrationModel registrationModel) {
            disposable = registrationRepo.loginForUser(registrationModel)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Response<RegistrationResponse>>() {
                        @Override
                        public void accept(Response<RegistrationResponse>
                                                   registrationModelResponse) throws Exception {

                            modelMutableLiveData.setValue(registrationModelResponse.body());
                        }
                    });
        }

        public LiveData<RegistrationResponse> getModelLiveData() {
            return modelMutableLiveData;
        }

       @Override
       protected void onCleared() {
                super.onCleared();
            disposable.dispose();
         }
    }
Abhishek Kumar
  • 4,532
  • 5
  • 31
  • 53
  • 8
    See LiveData as a data holder thing and nothing else. ==> YES – Lou Morda Jan 18 '19 at 18:42
  • 4
    Nice example. You forgot to declare the disposable and it would be nice to clear them in `onCleared`. – Snicolas Jun 21 '19 at 15:39
  • Could you please explain how livedata is synchronous? As far as I know we can send Livedata object to another thread and then that thread can postvalue which observer can listen to in the MainThread. – Hitesh Bisht Jun 22 '19 at 15:27
  • If you again read what I wrote it means you can't work on another thread just ( YES, I used "just" even there ) using LiveData as you can do using RxJava – Abhishek Kumar Jun 23 '19 at 04:55
  • Isn't lifecycle a big differentiator for LiveData? You 1. describe what your pipeline needs to do and what are your end results, 2. subscribe to the outcome in "observe" clauses, AND then 3. the pipeline is only being operated if your lifecycle state allows it. – Srg Aug 21 '19 at 07:09
  • There is some nice extension functions - `Publisher::toLiveData` and `LiveData::toPublisher` (depending on the V - VM data flow) - `androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycleVersion` mitating the `Subscriber` in Rx chains and disposing in most casas. – Mark Jun 13 '20 at 10:40
  • 3
    I consider using Rx for network calls an anti-pattern. Most things aren't streams. I know. It's a shocker. But they aren't. People who build their life around Rx say they are, but they really aren't. Unless you're using a subscription, a network call has a single result. And a stream with a single result is just dumb. It's like treating everything like a nail because you have a hammer. – funct7 Oct 10 '20 at 22:04
  • @funct7 Most things aren't streams -> TRUE. Though I understand that Network calls are mostly Single and not streams, but we can still use Rx for that sake of easy operators and easy handling of threads. Anyway you don't encounter streams in android that easy unless you work with real-touch events, search queries etc. – Abhishek Kumar Oct 11 '20 at 16:45
33

In fact, LiveData is not an essentially different tool to RxJava , so why was it introduced as an architecture component when RxJava could have easily managed the lifecycle by storing all the subscriptions to observables in a CompositeDispoable object and then disposing them in onDestroy() of the Activity or onDestroyView() of the Fragment using only one line of code?

I have answered to this question fully by building a movie search app once using RxJava and then using LiveData here.

But in short, yes, it could, but that would need first overriding the relevant lifecycle methods besides having the basic lifecycle knowledge. This still might not make sense for some, but the fact is that according to one of the Jetpack sessions in Google I/O 2018 many developers find lifecycle management complex. The crash errors arising from not handling lifecycle dependence might be another sign that some developers, even if knowledgable of lifecycle, forget to take care of that in every Activity / Fragment they use in their app. In large apps this could become an issue, notwithstanding the negative effect it could have on productivity.

The bottom line is that by introducing LiveData , larger number of developers are expected to adopt MVVM without even having to understand the lifecycle management, memory leak and crash. Even though I have no doubt that LiveData is not comparable with RxJava in terms of capabilities and the power it gives to developers, reactive programming and RxJava is a hard-to-understand concept and tool for many. On the other side, I do not think LiveData is meant to be a replacement for RxJava–it simply cannot–but a very simple tool for handling a controversial widespread issue experienced by many developers.

** UPDATE ** I have added a new article here where I have explained how misusing LiveData can lead to unexpected results. RxJava can come to rescue in these situations


Ali Nem
  • 5,252
  • 1
  • 42
  • 41
  • 2
    "why was it introduced when RxJava could have easily managed the lifecycle by storing all the subscriptions in a CompositeDispoable and then disposing them in onDestroy() of the Activity" - `LiveData` would dispose in `onStop` actually – arekolek Jun 21 '18 at 11:47
  • @arekolek from my understand: even to handle the CompositeDispoablewe have overwrite the life-cycle methods. But in Live data all will include in single line of code. So we are saving minimum 20 lines of code. – Suresh Oct 26 '18 at 17:20
  • We can define a baseFragment and define Disposable[] subscriptions() method to be overriden by all the derived fragments , call this method in onCreateView and add the return value in a CompositeDisposable, dispose that in onDestroyView, no more forgetting. – android2013 Jan 06 '19 at 11:23
  • It's not only about disposing. Using RxJava, you have to dispose at onStop, then subscribe again in onStart/onResume, handle configuration changes, and do a bunch of other stuff. That's why there's so many crashes using RxJava. LiveData handles all that, but is not as flexible as RxJava. – owl777 Jan 29 '19 at 19:02
27

As you may know in the reactive ecosystem we have an Observable that emits data and an Observer that subscribes( get notified) of this Observable emission, nothing strange is how works the so called Observer Pattern. An Observable "shouts"something, the Observer get notified that Observable shout something in a given moment.

Think to LiveData as an Observable that allows you to manage the Observers that are in an active state. In other terms LiveData is a simple Observable but also takes care of the life cycle.

But let's see the two code cases you request:

A) Live Data

B) RXJava

A)This is a basic implementation of LiveData

1) you usually instantiate LiveData in the ViewModel to maintain orientation change (you can have LiveData that is read only, or MutableLiveData that is writable, so you usually expose outside from the class LiveData)

2) in the OnCreate method of the Main Activity(not the ViewModel) you "subscribe" an Observer object (usually an a onChanged method)

3) you launch the method observe to establish the link

First the ViewModel (owns the business logic)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

And this is the MainActivity( as dumb as possible)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val ViewModelProvider= ViewModelProviders.of(this).get(ViewModel::class.java)

        ViewModelProvider.observe(this, Observer {//Points 2 and 3
            //what you want to observe
        })


        }
    }
}

B)This is the basic implementation of RXJava

1) you declare an Observable

2) you declare an Observer

3) you subscribe the Observable with the Observer

Observable.just(1, 2, 3, 4, 5, 6) // Point 1

   .subscribe(new Subscriber() {    //Points 2 & 3
       @Override
       public void onCompleted() {
           System.out.println("Complete!");
       }

       @Override
       public void onError(Throwable e) {
       }

       @Override
       public void onNext(Double value) {
           System.out.println("onNext: " + value);
       }
    });

In particular LiveData is used with Lifecycle and often with ViewModel(as we have seen) architecture components. In fact when LiveData is combined with a ViewModel allows you to keep updated in real time every change in the Observer, so that the events are managed in real time where is needed. To use LiveData is strongly recommended to know the concept of lifecycle and the relative objects LifeCycleOwner/LifeCycle, also I would suggest you to have a look at Transformations, if you want to implement LiveData in real life scenarios. Here you can find some use cases from the great commonsware.

To wrap up basically LiveData is a simplified RXJava, an elegant way to observe changes across multiple components without creating explicit so called dependency rules between the components, so that you can test much easier the code and make it much more readable. RXJava, allows you to do the things of LiveData and much more. Because of the extended functionalities of RXJava, you can both use LiveData for simple cases or exploit all the power of RXJava keep using Android Architecture components as the ViewModel, of course this means that RXJava can be far more complex, just think has hundreds of operators instead of SwitchMap and Map of LiveData(at the moment).

RXJava version 2 is a library that revolutionized the Object Oriented paradigm, adding a so called functional way to manage the flow of the program.

Sam Hanley
  • 4,707
  • 7
  • 35
  • 63
trocchietto
  • 2,607
  • 2
  • 23
  • 36
4

LiveData is a subset of the android architecture components which is developed by the android team.

With the live data and other architecture components, memory leaks and other similar issues are handled by architecture components. Since it is developed by android team, it is the best for android. They also provide updates that handle new versions of Android.

If you only want to use in Android app development, go for the Android architecture components. Otherwise, if you want to use other Java app, like web app, desktop apps, etc., use RxJava

Zoe
  • 27,060
  • 21
  • 118
  • 148
SIVAKUMAR.J
  • 4,258
  • 9
  • 45
  • 80
  • I've attempted to clarify your answer. If I've in any way conflicted with your original intent, feel free to edit. If you do though, please try to make it clearer than the initial revision. The last part of your answer honestly didn't make sense. – Zoe May 04 '19 at 14:12
2

LiveData as a data holder thing and nothing else. We can also say LiveData is Lifecycle aware consumer. LiveData is strongly recommended to know the concept of lifecycle and the relative objects LifeCycleOwner/LifeCycle, you get transformation and stream capabilities for your business logic and lifecycle aware operation for your UI.

Rx is powerful tool that enables to solve of problem in an elegant declarative style. It handles business side options or Service Api operations

Attif
  • 1,158
  • 13
  • 17
2
  • LiveData partially equals to Rx Subject or SharedRxObservable

  • LiveData manages lifecycle of subscription but Rx Subject subscription should be created and disposed manually

  • LiveData doesn't have termination state but Rx Subject has OnError and OnCompleted

Sergey M
  • 93
  • 2
  • 4
1

Comparing LiveData to RxJava is comparing apples with fruit salads.

Compare LiveData to ContentObserver and you are comparing apples with apples. LiveData effectively being a lifecycle-aware replacement for ContentObserver.

Comparing RxJava to AsyncTask or any other threading tool is comparing fruit salads to oranges, because RxJava helps with more than just threading.

straya
  • 5,002
  • 1
  • 28
  • 35
0

My simple answer is don't use RxJava. It is way overly complicated and abused. For all the projects using RxJava, they are hard to maintain and hard to debug. RxJava does things asynchronously, using threads within it to dispatch the requests, in general this is totally unnecessary, and if it is needed, Kotlin coroutine does a better job in perhaps 99% of the time.

Ray
  • 16,025
  • 5
  • 31
  • 51
-2

LiveData and RxJava are both reactive programming libraries that can be used to handle data in Android apps. They have both been around for a while and have their own strengths and weaknesses.

LiveData

Pros: Easy to use. Lifecycle-aware, so it only updates observers that are in an active lifecycle state. Well-integrated with Android Jetpack libraries. Cons: Not as powerful as RxJava. Can only be used to observe data changes. RxJava

Pros: Very powerful. Can be used to handle a wide variety of data tasks, such as network calls, database operations, and UI updates. Has a large community of developers and libraries. Cons: More complex to learn and use than LiveData. Not lifecycle-aware, so you need to manage subscriptions manually. Example

Here is an example of how to use LiveData to observe a data change:

class MyActivity : AppCompatActivity() {

private val liveData = MutableLiveData<String>()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_my)

    // Observe the LiveData and update the UI when the data changes.
    liveData.observe(this, { newData ->
        textView.text = newData
    })

    // Set the initial data.
    liveData.value = "Hello, world!"
}

} Here is an example of how to use RxJava to observe a data change:

class MyActivity : AppCompatActivity() {

private val observable = Observable.create<String> { emitter ->
    emitter.onNext("Hello, world!")
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_my)

    // Observe the Observable and update the UI when the data changes.
    observable.subscribe { newData ->
        textView.text = newData
    }
}

} In this example, both LiveData and RxJava can be used to observe a data change and update the UI. However, LiveData is easier to use and more efficient, as it only updates observers that are in an active lifecycle state. RxJava is more powerful, but it can be more complex to learn and use.

Which one should you use?

The best library to use depends on your specific needs. If you need a simple way to observe data changes and update the UI, then LiveData is a good choice. If you need more power and flexibility, then RxJava is a good option. However, if you are new to reactive programming, it is best to start with LiveData.