ReactiveX – A Brief Introduction
Taking the definition straight from reactivex.io –
ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.
You might be familiar with Iterators and Iterables that is based on a pull model. In Rx programming, Observers and Observables are used instead. Based on a push model, an Observer can subscribe to a data stream ie Observable to receive notifications on a particular piece of data and execute events accordingly.
ReactiveX provides a multitude of operators to transform, filter, select and combine Observables.
Example how a high-order function is applied on Iterables and Observables
ReactiveX programming with asynchronous data streams
Although not a new concept, asynchronous events which use data streams from events such as onclick, on-hover, slide, drag, etc events to produce an output – have been around since the rise of modern-day web apps.
Using ReactiveX, you are essentially creating a layer of abstraction of your code to handle data streams from a variety of inputs types. This lets you focus more on the business logic of the program than spending time figuring out the implementation for each stream.
With ReactiveX programming, almost anything can be used as a data stream. Variables, user inputs, properties, data structures, cache, etc even a Twitter feed could be fashioned into an input stream whose data values can be are taken from events you are interested in. You can even map data values from one stream to another.
Before ReactiveX programming – Activity Lifecycle Methods & The Callback Hell
Activity lifecycle methods (which run on the Main Thread) are used as a contract between the apps and OS to give feedback on the current stage of activity in an app. If too much work was allocated to the activity lifecycle thread, it would slow down the processing of that thread.
The earlier ideology was to load one of the lifecycle methods with extensive work without taking into consideration the execution time needed.
The main thread which handles UI updation, touch events, and even the activity lifecycle – would also be slowed down due to the heavy load on a particular lifecycle thread, which ultimately leads to slow or sluggish apps.
Callbacks – AKA the “Callback Hell”
Due to its low composition, the traditional nested callback pattern would have to go through a lot of work to throwback errors back to the original callback.
To put it in perspective, for every asynchronous task, one would need to –
- Treat the callback as a variable to prevent a memory leak from occurring (eg during onStop).
- Cancel the Async Task to prevent any work from being done till the issue is resolved.
- Checking if is canceled is set to true periodically.
In a nutshell, the code becomes extremely complex and messy if more callbacks are present.
Nowadays, mobile apps deal with a multitude of real-time events simultaneously, to create interactive user experiences. Developers are looking for a more clean and streamlined solution with less coding required and ReactiveX seems to be that answer.
Why Developers Love Using Rx programming & Why You Need To Use RxJava & RxSwift for App Development
1 ) Simplified Multi-Threading
Multi-threading whether on Java or Swift can be a pain in the rear to code, there are always a lot of situations to take into consideration.
Even when executing even a simple code on the background thread and getting results back on the UI thread. This can result in messy and complex code.
With RxSwift or RxJava, you can simplify complex operations with less code complexity and bugs. One can listen to an event on the main thread, react in the background, and output the results on the main thread again all in a much more simplified version of the code, using Rx programming.
All while allowing app developers to perform complex operations on specific threads while maintaining proper synchronization between threads.
Finally, with ReactiveX programming, all threading and lifetime management is implicit ie they have managed automatically.
Consider the code snippet that uses observeOn with different schedulers mentioned
2 ) Clean Code Architecture
Clean code architecture revolves around one major dependency rule – The inner layers should not know anything about the outer layers ie the dependency should only point inwards.
Using an onion-like shape, the code is separated into layers following the dependency rule. As seen in the use of MVVM and other MVC components. Rx allows the developer to build multiple channels of communication between the architecture layers while maintaining their independence.
Separation of concerns = Loosely Coupled Components = Less code = Cleaner Architecture with Rx
3 ) No Callback Hell/ Simple Error Handling
When dealing with large sets of complex asynchronous operations in an app, you will usually end up putting in a lot of extra and repetitive code just to handle sudden scenarios.
Rx lets you put the error handling logic all in one place and deals with the error propagation itself as compared to the traditional callback pattern when one must deal with a lot of work to propagate errors back to the original callback.
If an exception is thrown during the execution, it will be returned in onError with Rx.
Where an Iterable throws an exception when an error takes place, an Observable simply calls its observer’s onError method.
4 ) A Developers Dream Pt. I – Declarative coding via Rx
As mentioned earlier Reactive X offers a layer of abstraction to the code written.
Asynchronous workflows may be easy to understand at a high level of abstraction but as developers know, when really actually writing the code one must deal with objects spreading to multiple layers via nested callbacks, Key-value observing(KVO), notifications, delegates etc.
Using the traditional OOP styles, even a simple login process involves multiple workflows from validating the user input, nested callbacks, loading assets, checking API resources, and more.
So how does Rx help?
By treating asynchronous events as a stream, Rx lets you create channels of communication for the subscribe to observe. Then, in a declarative manner, the subscriber can then specify what happens to each event when they occur.
Hence with just a few lines, Rx would enable you to describe a complex workflow. Consider this sign-up process simplified with Rx, using drivers.
5 ) A Developers Dream Pt. II – Multi-Platform
Imagine creating reusable components at ease, components that can be ported to different languages and platforms – Well that’s what Rx programming offers with standardization of its structures and operations.
RxJava, RxSwift, Rx.Net, Rxrb, RxPY, RxGroovy, etc the list goes on, making the switch to ReactiveX style, a much easier process. You can refer here for more supported languages and platforms
To sum up
ReactiveX programming provides a variety of improvements in various areas such as coordination of asynchronous tasks, platform portability, thread safe storage types, loose coupling of components, and data dependencies.