RxJava is Dead, What Can We Learn From its Demise?

RxJava, once the hottest framework in Android development, is dying. Its former fans moved on, no one talks about it at software conferences and new developers don’t boast their RxJava chops on social media. In this post, I’ll take a moment to reflect on the history of this framework in Android ecosystem and see which lessons we all can learn from it.

RxJava Popularity Over Time

[I wrote this section back when the idea that RxJava is dying had been controversial. Today, RxJava is dead and no one needs convincing anymore. I decided to leave this section in the article to demonstrate a useful framework for analyzing tech trends.]

I’m pretty sure that some readers will be outraged by my claim that RxJava is dying. Let me explain how I arrived at that conclusion.

First, let’s look at the search interest of the keyword “rxjava” on Google:

As you can see, searches for RxJava peaked in May 2017 (that’s when Google announced official support for Kotlin in Android), plateaued for about a year and then started their gradual, but consistent decline. As of today, RxJava have already lost more than 50% of its “search interest” compared to the peak value.

Second, let’s examine the stats from StackOverflow Trends:

The picture is very similar.

The main counter-argument to my interpretation of the above data is that these graphs might reflect maturity and widespread adoption of RxJava, not its demise. To demonstrate why that’s not the case, let’s compare RxJava’s, Retrofit’s and AsyncTask’s stats from StackOverflow Trends.

First, let’s compare RxJava to Retrofit:

Retrofit is one of the most popular and mature frameworks in Android ecosystem and StackOverflow Trends reflect this fact. The rate of new questions is relatively stable. That’s especially impressive in light of the fact that the overall rate of Android-related questions is on decline. RxJava’s stats are strikingly different from Retrofit’s.

Now let’s see how RxJava stacks against AsyncTask, which had been officially deprecated several months ago:

The striking similarities between these graphs leave no room for doubt in my opinion. RxJava is dying and it’s time for Android community to come to terms with this fact.

Fundamental Problems With RxJava

One very interesting question we can ask is whether the demise of RxJava was predictable. In my totally subjective opinion, the answer to this question is “yes”. I can’t say that making such a prediction was trivially simple, but the writing had always been on the wall. So, let’s discuss the fundamental problems that destined RxJava to its sad fate.

The biggest issue with this framework is its complexity. It results in enormous learning curve that pretty much negates any potential benefit RxJava could theoretically have. In addition, this framework is completely unintuitive to “classically trained” software developer, so you can’t pick it up on the fly and infer the functionality of RxJava code from the surrounding context. Therefore, every developer who will read the code that uses this framework in the future will need to learn it.

Fundamentally, RxJava’s complexity is a direct consequence of a violation of the Single Responsibility Principle. You want to create a framework for glorified observers? Be my guest. Now you want to throw multithreading into the mix? Well, you step onto a shaky ground, but it can work, I guess. What, you also added an insane amount of cryptic operators?! Oops, you’ve just created Frankenstein’s monster. Good luck controlling this thing.

The second issue is that RxJava is very intrusive framework and it spreads in codebases like cancer. Even if you’d like to limit its impact to just handful of classes, it’s tricky to convert a component that exposes RxJava-based API into “standard” Observer design pattern. Therefore, the moment you add a bit of RxJava “magic” into your app, you most probably plant a seed of a much bigger tree. This process becomes pretty much irreversible if you also unit test your code. Then, RxJava contaminates both your production code and tests, so there is no going back.

Lastly, RxJava never received either official endorsement or support, which is problematic for such complex and intrusive framework. If official guidelines and tutorials would promote and use RxJava, then it would become “the standard”. That wouldn’t make its fundamental flaws go away, but, at least, it would make an average developer familiar with this technology. Without official adoption in the ecosystem, any project that used RxJava basically became strongly coupled to the fate of a questionable third-party dependency. It’s a nightmare from architectural point of view.

Why RxJava Was Relatively Popular at One Point

Taking into account RxJava’s flaws and associated risks, it’s surprising that it did get any traction in Android ecosystem at all. How comes? In my opinion, there were just two main factors that fueled RxJava’s adoption.

The main selling point of RxJava has always been that it’s better than AsyncTask. What does “better” mean here? To be honest, I’m not sure. However, countless developers, advocates and conference speakers contrasted these two frameworks. I’ve just googled “rxjava Android”, and the first three results also mention AsyncTask. Marketing-wise, this comparison was a good move. AsyncTask had already had a very bad reputation, so it made a perfect straw man for RxJava. However, this comparison was also flawed on many different levels.

Most importantly, presenting RxJava and AsyncTask as the only alternatives was a false dichotomy. As I wrote in my article about concurrency frameworks, bare Thread class and thread pools have always been very good options as well. It’s not a coincidence that after they deprecated AsyncTask, today Google recommend thread pools as a replacement in Java codebases.

But even forgetting about the false dichotomy, I’m really not sure that RxJava is any better than AsyncTask. It’s more reliable, sure, but it’s also much more complex and invasive. Today, when both AsyncTask and RxJava are legacy technologies, I’d rather refactor a codebase that contains AsyncTask’s than a codebase that contains RxJava.

Interestingly, RxJava never got any considerable traction among backend developers, even though it came from the backend world originally. In my opinion, the fact that they didn’t have AsyncTask to construct the straw man is one of the main reasons for this discrepancy.

The second factor that contributed to RxJava adoption was heavy marketing by its fans, some of whom were among the most prominent figures in Android community. At some point, you just couldn’t read a weekly newsletter or attend a conference without being preached about RxJava’s greatness. Now, that’s not something exceptional. We, developers, like our toys, so we naturally talk about them. What was very off is the personal aggression with which any criticism towards RxJava was met.

“You don’t know what you’re talking about”, “you hate everything new”, “you just don’t want to learn”, “according to you, we should code in Assembler”, etc. These were the standard responses to criticism. However, my favorite response is this:

This comment stuck with me because it’s so beautifully articulated. Really, it’s very funny and even poetic. I can appreciate that. However, it’s also fundamentally wrong.

First of all, today we know that my criticism was spot on and the “onset of automobiles” was very short. But the bigger problem here is the second part which concerns “building something large with this approach”. That’s a very common argument invoked by fans of pretty much anything, not even tech-related. We’ll get to this point a bit later.

So, straw man in the form of AsyncTask and high-profile promotion campaign, these were the main reasons which fueled community’s interest in RxJava.

The Future of RxJava

As far as I can see, the glorious days of RxJava are in the past and its future is grim. Since it didn’t get traction outside of Android, loss of popularity in Android ecosystem means loss of popularity in general. Therefore, unless something unexpected happens, RxJava will spiral down into complete irrelevance in 1-2 years.

Now, don’t get me wrong. RxJava will stick around for much longer. After all, developers will need to maintain all that code which has been hastily written during RxJava hype season (though these will probably be different developers from the ones who wrote it originally). However, the framework itself will become legacy and it will become more and more difficult to attract developers into projects that rely on RxJava extensively.

Some developers believe that RxJava died only for Kotlin projects, so if you have Java codebase then it won’t become a problem there. I think that, on the contrary, RxJava will become much bigger problem in Java codebases. Especially if those projects will need to migrate to Kotlin in the future. In general, in my opinion, using RxJava in Android world today is much riskier than using Java.

Many Other Frameworks Disappeared Before, So RxJava isn’t Special

Some RxJava fans found peace in claiming that RxJava is no different from any other framework which lost its popularity, so let’s move on, nothing to see here. While this thought can be comforting for those who invested tremendous effort into RxJava (either as users, or as maintainers), I think it’s not exactly correct and steers us away from learning hard, but important lessons. So, let’s discuss why RxJava is special.

The crucial difference between RxJava and most other frameworks is the scale of the loss.

For example, similarly to RxJava, we never really needed AsyncTask and it died too. However, compared to RxJava, AsyncTask consumed almost negligible effort on developers’ ramp-up and wasted much less attention span of the wider community. It’s also much, much simpler to maintain or refactor out of the existing codebases. So, compared to RxJava, even AsyncTask looks like a very successful framework.

The only fiasco of a comparable magnitude in Android world which I can think of is Loaders framework. It was even worse than RxJava in pretty much any dimension, wasn’t needed to begin with, consumed huge amount of community attention and then became irrelevant, quickly. However, Loaders was an official framework from Google, so you couldn’t really ignore it. Therefore, even the case of Loaders is very different from RxJava.

All in all, I think that RxJava’s story in Android is unique and presents an opportunity to learn some important lessons.

Lessons Learned

So, what can we learn from the meteoric rise of RxJava and its even more meteoric fall?

Well, the first lesson is that complexity and steep learning curve are red flags. If an average developer can’t figure out what a piece of code does by just reading it, it’s a big problem. Now, in some cases, complexity is essential. For example, advanced image processing algorithms will be complex no matter what. But if you need these algorithms in your app, there is no way around that complexity. In contrast, no one ever really needed RxJava. Therefore, all this excessive complexity could easily be avoided.

Then there is this simple, but so often overlooked fact that not every hot and new technology which becomes popular at conferences is worth an investment of your time. This point alone deserves an entire article on its own, so I won’t dive into it here. However, realize that many frameworks that are dead today were the topics of many conference talks in the past. And most of these talks were given by enthusiastic, honest and capable developers, who praised that tech. Examples from the top of my head: SyncAdapter, AsyncTask, Loaders, Realm, Volley, Xamarin, Cordova, etc. So, the fact that a tech is discussed at conferences is meaningless when it comes to evaluating its merits. In fact, I will even go as far as saying that if some tech is discussed at conferences a lot, that’s a sign that this tech is not your best bet.

Lastly, let’s get back to the argument that you can’t evaluate some piece of tech before “you’ve built something large with it”. This is a standard trick in many propaganda campaigns. It’s basically an attempt to deflect the conversation from the voiced criticism and picture the critic as not having enough knowledge and/or experience to have any say in the discussion. Now, let me be absolutely clear: I’m not saying that prominent Android developers consciously planned a full-blown propaganda campaign. What I say is that this is one of these dirty tricks that we, humans, employ subconsciously to protect our beliefs. It’s a part of our natural response.

I don’t mean to say that “you’ll see benefits only at scale” is an invalid argument. In some cases, it’s a fact. However, “scale” benefits should be stated explicitly and subjected to external criticism as well. If they are real, it shouldn’t be that difficult to describe the conditions in which these benefits become relevant.

So, the last lesson we can learn from RxJava is that if advocates of some tech can’t keep the discussion professional and attempt to either discredit, or flat-out offend the critics, chances are that what they “sell” isn’t that good.

Examples

In this section I want to put everything I discussed above into more practical terms using two examples.

The first example is AirBnb’s MvRx framework. They announced it in August 2018 and I immediately realized that they had made at least two mistakes related to RxJava.

The first mistake was to use RxJava in this framework at all. They had probably started working on MvRx long before the official announcement, so, maybe, back then RxJava was still “hot”. However, the decision to couple their entire codebase to RxJava in 2018 was questionable because, by then, it was already clear that Android community loses interest in this framework. Given the fact that AirBnb employs tens of Android developers, extra-strong coupling to a legacy framework will probably come to bite them in the future.

Then there is the name, MvRx. As you know, naming is one of the most difficult things in software, but AirBnb’s choice is still very odd. And I’m not talking about the fact that inventing new variants of MVx abbreviation is a questionable practice. What I consider a real mistake here is the fact that they basically tied the public perception of their new framework to a third-party dependency. RxJava is in free fall now and MvRx, due to its name, is tied to it with a rope.

I don’t know what’s going on within AirBnb, but I suspect that, in light of the loss of business due to pandemic, they aren’t concerned with unfortunate tech choices at the moment. But there is no doubt in my mind that MvRx will become a problem for them both in terms of attracting new developers and in terms of ramp-up and maintenance costs. Therefore, I fully expect them to either refactor RxJava out of MvRx, or ditch it completely. Both paths involve a major investment into refactor of their codebase. I also won’t be surprised if they decide to change the name of this framework.

The second example is one of the best libraries for Android, ReactiveNetwork by Piotr Wittchen.

Most Android apps need to know whether they have internet connectivity or not. However, even though relatively simple API has been available since the very early days, it wasn’t reliable. For example, you couldn’t detect so-called “captive portals” on public Wi-Fi networks and other types of restricting proxies. ReactiveNetwork is a highly configurable library which allows you to handle the whole range of network states, with relative simplicity.

In my opinion, the only reason ReactiveNetwork isn’t as popular as, say, Glide, is it’s RxJava-based API. Most developers wouldn’t like to take this dependency and learn how to use RxJava to just monitor network state. Therefore, the potential audience of this library is limited to projects which already use RxJava and projects where reliable handling of network state is critical. That’s really unfortunate.

Now, open-source maintainers don’t owe me anything and are free to choose whatever technologies they want. However, I believe that most people who put their work in public domain do want to see their baby being widely adopted. RxJava interferes with this goal and severely limits the potential audience of any open source library. In case of MvRx, I don’t mind that because I wouldn’t recommend this framework in any case. In case of ReactiveNetwork, I’m really sorry for that because I constantly recommend this library, but also have to add a disclaimer that it uses RxJava.

Conclusion

All in all, in my opinion, RxJava in Android was a fiasco. It consumed enormous amount of community effort and attention, contaminated many codebases, didn’t bring any value and, as of today, I can say that it pretty much died. It’s my hope that we will be able to extract at least some lessons from this story and, maybe, avoid another cycle of churn in the future.

I know that this article will be hard to read for many developers who learned, used or maintained RxJava. Some will even argue that since they already use this framework and it makes them productive, the best path forward for them is to just keep using it. However, if you care about long-term maintainability of the code you write today, RxJava doesn’t make a cut.

I totally understand how you feel if you’ve been RxJava user or fan because I myself used SyncAdapter, ContentProvider and Loaders in the past. However, the sooner you’ll realize that it’s a classical sunk-cost fallacy, the better for you.

As usual, thanks for reading. You can write your comments and criticism below, but please keep the discussion civil.

Check out my premium

Android Development Courses

29 comments on "RxJava is Dead, What Can We Learn From its Demise?"

    • Hi Ilya,
      I have complaints about Coroutines, but, in my opinion, if you work in Kotlin-only projects, you should use them for concurrency. This seems to be the best long-term strategy.

      Reply
  1. First of all, I absolutely adore this article. It is very good read. I want to add a few remarks:

    > “The second issue is that RxJava is very intrusive framework and it spreads in codebases like cancer”
    I would put this on the first place, because we maintain way more code than we write new code, and I’ve seen how painful it is to maintain such code. We’ve successfully managed to get rid of the RxJava in the project I am involved now, but it was a long and painful experience. If it was possible to have that code isolated, it might have been easier to keep up the maintenance, despite the complexity of the RxJava.

    I believe that RxJava trends that are still there in the stats you shared are becasue of the projects that need to be maintained, not because of new projects.

    A little bit about the hypes. I remember very well the times when those rather unproductive discussions were happening, and it was so piry to see that insane number of developers took the hype of the RxJava without really checking whether it’s the tool they really needed. It’s unbelievable that it still happens novadays. We, programmers are intellectual folks. IMO, an intellectual’s duty is to constantly criticise the sense. That’s part of the professionalism. Yet, we are still failing to learn from ours and the mistakes of the others. We must take criticism seriously, but not personally. That’s the way towards the better. Taking criticism personally prevents a productive discussion, and will lead to attacking-defending discussion which is wasteful.

    Folks are still blindly follow the recommendations from some vocal people on social media without taking their time to evaluate.
    Now, please don’t take me wrong. I don’t want to blame the vocal folks on Internet, I just want to point out that some of them are not doing a good job to describe the drawbacks from the given topic, and they talk about the positive things only. I want to point out the following example:
    >”until you’ve built something large with it”
    Does it mean that the technology is meant to be used only to build something large? What if I am in a fairly simple or medium project? What if 99% of the projects are not “large”? How do we define “large” to begin with? If this technology, among all the other hypes around us, was described properly to people, probably they wouldn’t feel bad for not using what “the cool folks use”, and they wouldn’t feel afraid for missing out something they don’t need at that given time.

    Thanks for writing this, loads of interesting topics opened which are really worth to be discussed.

    Reply
    • Indeed, oftentimes people dismiss criticism with the “but at scale” argument, people have made it for MVI, for MvRx, for Redux – but it is always nebulous as not only does it stand for “but it works for us” (with our knowledge that you don’t have, in circumstances that you’ll probably never have), but their solution is non-verifiable for correctness.

      How often have I fought basically *wars* about “but if your app is completely described with ‘stateless’ Rx operation chains, how can you possibly restore state after process death?” the common answer being “we don’t”.

      So even “at scale”, if I take Reddit as an example, you see bugs like deep-linking into a message, and you see both Content and Empty view on top of one another. Is, then, scale actually the number of devs on a team, rather than the importance of behavioral correctness?

      But then, how do you guarantee behavioral correctness with Rx? If we take the talk “Managing State with RxJava” into account, most Rx chains are riddled with potential race conditions. Without an understanding of concurrency fundamentals, not even Rx will save anyone from multi-threaded access to mutable non-synchronized non-atomic state.

      . . .

      Nonetheless, I personally think Rx is a powerful tool, although only about… 8% of it is needed? BehaviorRelay, Observable, Single – those are already capable of solving 99.8% of problems. Operator-wise, all I need is filter, map, flatMap, switchMap, zip, debounce, and combineLatest (and of course subscribeOn/observeOn, and doOnSubscribe/doFinally). This is enough for about 98% of cases, too. Sometimes you need buffer. So why are there 100+ other operators like `amb`, while you have to pull in extension for something essential like `valve`?

      Rx’s customizability is abysmal, you cannot trust any of the code you write for it. Rx is so micro-optimized, that its internals are extremely hard to read – and that’s assuming you’ve even heard of “operator fusion” and read the custom operator docs. I’d rather just not build a custom operator, and won’t trust any custom operators built by anyone (looking at you, RxRedux).

      However, I actually still added Rx to a reasonably new project. Why? Because the alternatives are not as mature: channels are on their way to deprecation (maybe?), flows are too new, coroutines have quirky exception handling, and… we’re out of alternatives. Yet I still see value in the ability to combine multiple observable primitives and **actually** create a reactive flow, a reactive state calculation – akin to a formula in an Excel sheet – rather than imperatively calculate a new state with `.copy().copy().copy()` as either of MVI, Redux, RxRedux, MvRx or any of these “single object state presentation” variants do where your state is a top-level `LiveData`. That in itself makes it impossible to make state calculation truly reactive, and most of MvRx/Orbit/[insert screen-level MVI state management framework here] is a workaround for this self-imposed limitation. Unnecessary.

      When Flows are truly stable, it might be a proper replacement for Rx. But for now, as long as one retains ownership of their state and uses Rx for actual functional reactiveness rather than… well, whatever people had been building on top of it, then Rx can be a powerful tool. Requires expert guidance and very concrete ground rules, though. It’s easier to ruin codebases with it than build good ones.

      —-

      Overall, this is a great article with a lot to take away from it. What seems shiny today, might be the cause of the fires in your codebase tomorrow, especially if you cannot truly trust its inner workings.

      My personal prediction points towards Koin (…and now the pitchforks point at me).

      Reply
  2. Thought-provoking article as always. One benefit of RxJava is escaping callback chaining. What do you recommend instead if that’s the primary goal rather than managing concurrency?

    Reply
      • I am still not convinced that you get same effects with your approach because of the cancellation. Disposing rx chain will dispose everything and I guess you would manually need to check if work was cancelled every step of the way. Can you ellaborate more on this? I also think that the main reason for rx becoming less popular is rise of kotlin and coroutines and not anything else.

        Reply
        • I think we’ve had several discussions about cancellation in the comments of that article. I also touched upon it in my article about use cases. TL; DR; you don’t really need to cancel absolute majority of concurrent flows. Just let them complete and ignore the result, problem solved.
          Unfortunately, that’s not something you can do with either Rx or Coroutines, so if you use these frameworks you must deal with cancellation and all the accompanying edge cases (most devs don’t even know about them).
          If Rx death would be related just to Kotlin and Coroutines, it would remain popular in Java projects. It’s not. Kotlin and Coroutines are only relevant here because devs who like new and shiny things ditched Rx in their favor, so Rx lost its most enthusiastic advocates. Even if Kotlin wouldn’t happen, RxJava would die. It would take more time, but the result wouldn’t change.

          Reply
        • Kotlin Flow can be used instead of rxJava. What’s nice about Flow is that because it’s written in Kotlin, you can create custom operators. Why on earth would anyone want to read through a 1000 operators in the rxJava docs to find something when you can quickly just create your own operator if one of the built-in ones isn’t available? Sorry, but I’ll go with Flow any day over bloatware rxJava.

          Reply
  3. Great article, as always.
    Can you explain more what you mean by “RxJava’s complexity is a direct consequence of a violation of the Single Responsibility Principle.”?
    How does it violate SRP?

    Reply
    • It’s pretty much what I wrote. RxJava attempts to be Observable, concurrency framework and also provide zillion other operators and functionalities. It’s a greedy framework which doesn’t have a specific purpose.

      Reply
    • As far as I know, as of today, there is no reliable way to execute background jobs in Android. Not even with SyncAdapter or WorkManager.

      Reply
  4. I’m not an android developer nor a java developer but I’m generally interested in knowing what kind of general patterns, frameworks and architectures work for people who deal with scale.

    I was really looking forward to reading why JavaRx is bad and all I got was ranting and arguments with no examples or direct comparisons how a “good” framework or architecture would work compared to “bad” javaRx.

    I don’t even understand what is the alternative you are suggesting as I think a lot of the post was just long opinionated ranting and tried to skip those and get to the technically sound parts.

    If you want an UI, which pattern do you think is better than property/small struct based observables, task based multi threading and listeners being passive and do not change application state?

    Reply
    • Two-three years ago we could argue whether RxJava is good or bad, but, today, this argument is not that important anymore. I shared my criticism of RxJava in the article. You obviously didn’t find it compelling, but that’s largely irrelevant.
      The harsh, but simple fact for Android devs is that RxJava is dying and will become problematic legacy dependency very soon. That’s the central point of this article. This will happen regardless of whether some developers like this framework or not, and whether the altrenatives are better or worse in their opinion. Developers who won’t accept this fact will be writing problematic code from maintainability point of view.
      I wrote this post for Android devs, so if you’re not one of us, it totally makes sense that it didn’t speak to you.

      Reply
  5. I still believe RxJava is a powerful tool, but as you stated, its complexity is too high for most of our use cases: it mostly replaced AsyncTask as a way to start a task in the background then come back to resume your work on the main thread. Problem is, not only did it not get officially endorsed by Google, but both Google and Kotlin tanked it by providing simpler alternatives: LiveData in Google’s MVVM architecture (which I see as a watered down Rx copy, missing some of the key features) and Kotlin’s coroutines (which are a much more intuitive way to pause execution on the main thread and resume it later… but is still very pervasive in your code base: all your functions basically have to become suspending ones).
    I’d be curious to compare RxJava’s fate to Dagger: its steep learning curve compares to RxJava’s, simpler alternatives have appeared, and for some time, it looked a bit doomed too until Google put it back on the front scene by endorsing it at lot during last year’s IO…

    Reply
  6. I’m personally still thinking that there is still a room for Rx in general. As you stated @Vasiliy, the framework as the Api, is complex, but in the other hand, you can also just use it with the simplest concepts, that are not harder that coroutines or others ones. Additionnaly, dev are more used to code with StreamApi, that decrease the learning curve of Rx.
    With chance, Rx also offers a huge number of operator, you may, time to time, use it to solve complex problems in a very simple and reliable way, because of the operator quantity, history and their implementation quality !
    Nevertheless, you may also fail quickly and strongly with Rx, but IMO, this is more due to architecture problem ! If the Rx streams is encapsulated and under control, you may just need a few operators to code 90 of your app, without any big issue.
    What ever framework you select, sw design issues or SOLID unrespect will still be there at the end !

    Reply
  7. I really appreciate this article for making me feel like I wasn’t going crazy when I found RxJava baffling and overengineered.

    Before getting into Android recently, I was an an iOS and JavaScript developer who always liked code to resemble plain English, expressing ideas simply and powerfully. There was that book comparing good JS to the spare prose of Hemingway. I dug that.

    But then I started maintaining an app that was full of confusing RxJava. It took me months to work out what it was all for, and why the functions would be arranged in such a tangled mess.

    I feel like there is an insecurity in Java World that creates monsters like Rx. As NodeJS grew in popularity, letting you express complicated processes in simple ways, Java engineers became defensive. They called JS a toy language. Java was a Ferrari, they said, and JS was Hot Wheels. Messes like Rx help to maintain the illusion that Java accomplishes all these special, complicated, delicately-engineered feats that you couldn’t just express in a few lines of some other language that values clarity and simple expression.

    Reply
  8. Nice Article. I see very few people mentioning the true advantage of RxJava on Twitter/Medium probably because they encountered a scenario where applying Rx makes sense to them as per their experience and it’s fine. Also, those guys invested a lot of time in Rx so it makes sense to them. Personally, I didn’t find myself stuck with any such situation, so applying Rx doesn’t make sense to me. I was able to solve most of my day to day problems with using language and android framework options. As you pointed in the article, even Google is now recommending to use Executor in their official doc(for java apps). I am using the executor way for the last 2-3 years and haven’t encountered any issues. Those who are thinking maybe this guy has not worked on large scale projects, I will suggest you guys to read this post (the author has a very nice explanation for this argument). Most of the devs are doing hype-driven development without even asking themselves, does applying Rx to each and every scenario really makes sense in their use case? Just look at the amount on amateur articles on medium with funny gifs & saying AsyncTask is a sin etc etc. All these novice articles just show a simple AsyncTask or Retrofit call in its Rx equivalent. Half of them doesn’t even mention to use compositeDisposable to cancel the subscription. These articles are relatively simple to understand and junior devs find it easy and apply it blindly. Rx is an external dependency. You want to have external dependency as minimum as possible. I recently started learning RxJava (to be honest just for interview purpose. The irony is for take-home assignment many companies have asked me to manually parse JSON, use no libraries for multithreading but when it’s time for f2f interviews then the interviewer will ask do u know Rx?).

    After spending a few weeks learning, I can relate some scenarios in past where I can apply Rx for a smaller code but just for those 2-3 scenarios I will still use traditional way and will not include an external dependency. Any external dependency will add more learning curve to a junior team member (especially if they are freshers). Why do you want to make it overly complex when there is a much simpler way of doing it by writing a few extra lines of code by using the language features.

    Don’t know how Rx became so popular in Android (even though it came from backend as the author said)

    Have started learning Kotlin but Coroutines seems powerful to me. Not because it is recommended by Google but I was reading about structured concurrency and its a computer science concept with its root all the way back to 1958(as per wiki). Was going through Structured Concurrency article in Wikipedia which says “Roman Elizarov independently came upon the same ideas while developing an experimental coroutine library for the Kotlin language”. Roman is a hell lot experienced person and I am sure the language designers have done extensive research regarding this.

    I will invest time learning Kotlin, Flow, Coroutines now rather than spending another two months on Rx and learning all its operators.

    Reply
  9. Observables are a handy abstraction. Especially the Observables/Async variant that the various ReactiveX implementations provide. That’s really not going anywhere.

    It’s curious that while RxJS may be over its explosive phase, it continues to gain popularity in the JavaScript/Typescript world. RxJS faces many of the same obstacles your rant describes here and seems largely unphased so far. I suppose there are many ways to account for the descrepency.

    Not the least of which is that RxJava a different beast than RxJS as they have very different multitasking/async environments. Even so, the popularity of RxJS is going to ensure that developers continue to be familiar with the underlying concepts.

    So until a better abstraction comes along and supersedes the Observables/Async mixup of ReactiveX, RxJava is just going to keep limping along. At least, that’s my prediction.

    Reply
  10. Im fairly new to development and need a framework for background work for the usual reason – i nearly got caught up in the reactive hype, glad to see you also feel its not simple to learn – ive spent a few full days already trying to consume content and learn the principles of RxJava for android and its already in my codebase. I thought it was the future, so this article was timely!
    Quite a surprise to see how sharply its falling off!

    So… I learn kotlin with coroutines and Flow instead?

    Reply
    • Hi Tom,
      Glad you managed to avoid going all-in on Rx. As I wrote in the article, if you write purely in Kotlin, then Coroutines is the way to go. For Java, you’ve got some alternatives, but I, personally, use ThreadPoster.

      Reply
  11. I LOVE this article, because I’ve been a software engineer for over 30 years now, and not until that last few years have I been so frustrated with a framework that is EXTREMELY over-complicated, convoluted, kitchen-sinky, has a HUGE learning curve, and basically has pushed me to go back to server-side engineering instead of even trying to work in Android any more. I’m looking for work now, and had an interview lined up for tomorrow, and have been refreshing my skills in MVVM and rxJava, but then got frustrated, did a Google search for “I HATE rxJava” and found this. I think I’m going to bail on the interview and look for server-side work. I have a ton of back-end experience too, original Spring, Spring-boot, etc. I don’t need the rxJava hype headaches and hours and hours of rummaging through neck-deep APIs to figure out how to move a piece of data from A to B. I have found in the world of software engineering that often egos and “look how complicated my cool tool is” often wins the day and produces a lot of APIs and tools that are just garbage. We’re here do GET SH**T DONE for our clients, not feel good at the end of the day that we were able to figure out some esoteric piece of code that in the old days we could have accomplished by simple calling a method and setting a value. Yes, streams and chaining are useful, but man, don’t try to complicate things on purpose with difficult to follow syntax, code arrangement, wrapping, etc.

    Reply
  12. To add to my last comment, a few years ago I was at a fintech firm where I introduced Kotlin, got everyone training, etc. They had already started using rxJava and so I had to try to catch up. A new app was being written and someone who was already very fluent in rxJava wrote the entire app using rxJava. I looked at the code, and the complexity was staggering and almost completely unreadable. It was a huge mistake IMO. A new developer coming along would have a VERY difficult time figuring out what was going on. I’m glad I have choices and can shed this behemoth once and for all. I don’t mind never again writing one line of rxJava. I’ve got better things to do frankly. When you build apps using rxJava, especially if you go all in and use as much of it as possible, you’re creating for yourself MOUNTAINS of tech debt that will live as long as that code lives.

    Reply
  13. RxJava is a godsend. It solves all the problems with combining data and concurrency. And the code you get is very concise and well structured. The only problem with RxJava is that now coroutines and Flows provide same functionality and now there is no single framework with the goodies.

    Reply

Leave a Comment