Reactive Programming with RxBinding
Developing a complex Android app that has lots of network connections, user interactions, and animations often means writing code that is full of nested callbacks. ReactiveX offers an alternative approach that is both clear and concise, to manage asynchronous tasks and events.
ReactiveX
ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming
RxJava
RxJava is a JVM implementation of ReactiveX, developed by NetFlix, and is very popular among Java developers.
What is Reactive Programming
Reactive programming is an asynchronous programming paradigm oriented around data streams and the propagation of change. This means that it should be possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease in the programming languages used, and that the underlying execution model will automatically propagate the changes through the data flow.
For example, in an imperative programming setting, a:=b+c would mean that a is being assigned the result of b+c in the instant the expression is evaluated, and later, the values of b and c can be changed with no effect on the value of a.
However, in reactive programming, the value of a would be automatically updated whenever the values of b and c change, without the program executing the sentence a:=b+c again.
Observable and Observer
There are two basic and very important items in reactive programming, Observables and Observers. Observables publish values, while Observers subscribe to Observables, watching them and reacting when an Observable publishes a value.
In simpler terms:
- An Observable performs some action, and publishes the result.
- An Observer waits and watches the Observable, and reacts whenever the Observable publishes results.
There are three different changes that can occur on an Observable that the Observer reacts to. These are:
- Publishing a value
- Throwing an error
- Completed publishing all values
A class that implements the Observer interface must provide methods for each of the three changes above:
- An onNext() method that the Observable calls whenever it wishes to publish a new value
- An onError() method that’s called exactly once, when an error occurs on the Observable.
- An onCompleted() method that’s called exactly once, when the Observable completes execution.
So an Observable that has an Observer subscribed to it will call the Observer’s onNext() zero or more times, as long as it has values to publish, and terminates by either calling onError() or onCompleted().
What are the RxBinding Libraries?
One of the benefits of using RxJava is the ability to compose asynchronous events in a more straightforward way. Complex UI interactions in Android can also be greatly simplified too, especially when there are multiple UI events that can trigger. To describe the interaction pattern with standard Android code, you would usually need to use a combination of both listeners, Handlers and AsyncTask. With RxJava and RxBinding, this logic can be greatly simplified and you can describe the interaction patterns between multiple UI components.
RxBinding is a set of libraries that allow you to react to user interface events via the RxJava paradigm. Let’s take a look at a few example.
This is how Android developers typically react to a text change for an EditText
Now the same thing, but written with RxBinding support:
Now the same thing, but written with RxBinding support:
In the example above, I use the RxTextView.textChanges() method to react only to the text change event. In traditional Android, we have to implement a full TextWatcher to accomplish this, wasting multiple lines of code because the beforeTextChanged event and afterTextChanged callbacks must also be implemented. This dead code simply pollutes the class and offers no additional value. With RxBinding I can achieve more control over what I want to react to in my application without the additional overhead in my codebase.
A Simple Example
For example, consider what you would need to create a simple registration form with two fields, username and email.
The registration form has these behaviours:
- The initial state of both fields are blank.
- If the field is valid according to the criteria, the text will be colored black.
- Criteria for email is a valid email using simple regex check.
- Valid user name if it’s more than 4 character in length.
- If the field is not valid, the text will be colored RED.
- The Register button is only active when both fields are valid.
If you used to create Android applications, you’d now how many handlers and anonymous classes you will write to track the state of the fields and to create the behaviour of the register button.
Setting Up RxBinding
To use RxAndroid in an Android Studio project, add it as a compile dependency in the app module’s build.gradle.
Creating an Observer and observables
As mentioned above we can create RxTextView.textChanges() observable to react to the text change event.We’d like to capture the text and print them in the ADB console.
When we run this app, we’ll get these output.
Transforming with Operators
Now, let’s implement the behaviour of the validity of each field. Map the text from each fields and verify.To achieve this we’ll define several Observables for each EditText. The condition of validity are
- UserName should be more than 4 characters in length.
- Email should match a simple regex validation.
Since RxBinding is applying RxJava paradigms to existing Android Views and Widgets, you can use RxJava operators to perform transformations on the stream of data that is emitted in real time.
The code is pretty straightforward.
- This is the email pattern we’ll use for email validation. We’re using classes from java.util.regex package.
- We create an Observable<Boolean> for the UserName and email.
Next we need to map the validity Observable to a color observable and subscribe to them to change the text Color.
The result is as expected.
Combining Observables
Lastly, we’d like to implement a use case where the Register button only enabled when both fields are enabled. For this we’ll need to combine two observables to one. To do that we use combineLatest method.When an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of a function.
Code will look like this:
Filtering Observables
The items from userNameValid, emailValid and registerEnabled are emitted on each user input. This causes the subscribers are called everytime the user type in the fields.
We only want the subscriber only called when the validity changes. For this, we’d need to call distinctUntilChanged() method on our Observables. Thus, the code becomes:
As usual, the complete source code for the examples used in this tutorial is available on github. Feel free to check out and use however you see fit.
Muchas gracias por tu aporte, me ayudo bastante para entender el manejo de la librerÃa y ya estoy ansioso de probarla. Gran trabajo.
ReplyDeleteThis comment has been removed by the author.
Delete