Xamarin Android Meets Reactive World

Xamarin Android Meets Reactive World

Fausto Bencosme
Nov 1 · 4 min read

I never had the opportunity to use the old-fashioned, standard way of creating some interactions or code in Android, using the idea of AsyncTask to solve problems of concurrency and parallelism in this ecosystem.

Since the beginning (lucky me), I started using Rx.

The Observer pattern done right.

A combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming.

I have read a lot of blogs, explaining and sometimes even warning others to think twice before using AsyncTask.

To be honest I cannot image myself solving complicated problems using this approach in my day-to-day work but fortunately, Rx is here to the rescue.

Imagine the case or scenario where you have to create a signup form where, in this particular case, is going to have the following requirements.

  • 5 fields: First name, last name, gender, email, password and confirmation password.
  • 1 button to submit the form.
  • Be able to submit a form pressing Enter key button from android keyboard.
  • Display a loading dialog when the form is processing.
  • In a case of any error, display it in each respective field.

This previous behavior can be achieved in a reactive way, by coding very succinct block. Check the snippet bellow and tell me if I am right or not :).

You may be wondering what in the world is:

view.RxClick()
view.RxTextChanged()
view.RxKeyPresseed()

Well, these are extensions methods used to abstract the idea of events handler to the reactive stream world, these things are really easy to create, see below how you can do it:

Briefly explained

Basically, the idea here is to take the latest value generated by the combination of the stream of values that came from the inputs (the form) and then, whenever the Enter key or the register button is pressed, I want to submit the form.

// Collect the 5 inputs values.
Observable.CombineLatest(
firstName .RxTextChanged(50).StartWith(string.Empty),
lastName .RxTextChanged(50).StartWith(string.Empty),
email .RxTextChanged(50).StartWith(string.Empty),
pwd .RxTextChanged(50).StartWith(string.Empty),
confirmPwd.RxTextChanged(50).StartWith(string.Empty),
gender .RxSelectedItem() .StartWith(Gender.None),
, Tuple.Create)
// Take the latest combination.
.SampleLatest(
// Either key enter pressed or register button clicked, continue.
Observable.Merge(
// Merge all input key press events.
Observable.Merge(
firstName .RxKeyPressed(),
lastName .RxKeyPressed(),
email .RxKeyPressed(),
pwd .RxKeyPressed(),
confirmPwd.RxKeyPressed()
).Where(_ => _ == Keycode.Enter)
.Select(_ => Unit.Default),
// Click event
registerBtn.RxClick()
)

Next, I want to clear out the possible errors it might have at the moment. It is something like starting the submission with a clean face, see how:

// Clean all errors.
.Do(_ => {
email.Error = null;
pwd.Error = null;
email.Error = null;
pwd.Error = null;
confirmPwd.Error = null;
}))

After the action cleans the input my next goal is to hide the keyboard and then submit the values to the server.

// Hide keyboard.
.Do(_ => HideKeyboard())

Notice that in the next line, line 29 to be more specific, I use the debounce operator in order to avoid multiple and unnecessary submissions.

// This implementation fires immediately.
.Debounce(TimeSpan.FromSeconds(2))

The last job to do here is to submit the values to the server, but at the beginning, we were asked to display a progress or at least to present in some way that the app is doing something.

We can do this is as follows:

// Send collected data to server.
.SelectMany(data =>
Service
.SignUp(data)
.WithProgressDialog())

Maybe at this point, you don’t know what WithProgressDialog() is, but it is something really simple: what it does is launch an AlertDialog and then when the stream finalizes, dismisses the dialog.

At the end, as you can see, what I do is taking the response from the server and, depending on the case of the result, I proceed to perform some action.

Really concise, huh?

.Subscribe(_ =>
_.Match(OnSuccess, OnFailed));
void OnSuccess(User u) {} // Do something
void OnFailed (Error e) {} // Do something

Code snippets:

RxSignUp

UiExtensions

NetworkHelpers

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade