RxJava and Retrolambda for Android

RxJava and Retrolambda for Android

In this article I will explain how to setup new Android Studio project and start using some of Java 8 features – lambda expression. I will also introduce you to RxJava and show you how using it in daily work will make your life easier.

You know that Java 8 comes with some great new features, including Streams. We still can’t use it on Android, and this is where RxJava comes in.

So what are Streams about? We could say they are just a set of data or collection which can be emitted. It can be an Array, HashMap, CharSequence or even clicks. Clicks?! Yes, let’s imagine you can treat click events as a normal Stream – every time user sends click event we just emit the next element.

What we will try to achieve here is just a basic screen with two EditText views and a Button. The Button will be disabled until we type something into EditText. I’m sure you know about TextWatcher, which is one of the biggest body Listeners. I will show you how we can use both RxJava and lambda syntaxes to implement this.

You will need Java 8 installed on your OS. I will not focus on how to create project at all so go ahead and create a new blank project with an empty Activity (I start with SDK version 17). I will name it MainActivity.

Open your project build.gradle file and add retrolambda plugin to it so it looks like this:


buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'me.tatarka:gradle-retrolambda:3.2.4'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Now we need to tell application build.gradle file to use Java 8. Let’s include retrolambda and RxJava library with additional RxBindings from Jake Wharton.


apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.broda.rxjava.rxtutorial"
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
}

Once we have this done, let’s open activity_main.xml file and add our views. We will focus on MainActivity.java file for now. First of all, we will need to make Observable objects from text, which we type into EditText views. We will use RxBindings, which is set of helpers to work with RxJava on Android.

        
    Observable emailObservable = RxTextView.textChanges(emailEditTextView);
    Observable passwordObservable = RxTextView.textChanges(passwordEditTextView);

How cool is that, huh? We don’t even have our TextWatcher here so we saved a couple lines of code already.

Right now we need check if we can enable a button. The condition is simple – once our inputs are non-empty, we can enable our button.


  Observable.combineLatest(emailObservable, passwordObservable, (c, c2) -> c.length() > 0 && c2.length() > 0)
    .subscribe(aBoolean -> button.setEnabled(aBoolean));

RxJava comes with great features to work with multiple Observables objects. We can use methods like merge, concat, zip or combineLatest. There is a great tool to visualize how those operators work. Go ahead and play with it a little.

In our example it is best to use combineLatest operator to validate our inputs. Once we combine our Observables we can subscribe to them. It is important to know, that until you subscribe to Observable Object it does not do anything at all. So you can create some Observables and subscribe to them in multiple places. If you would like to go deeper you can read about Subjects, which are another great feature of RxJava.

Allright, lets subscribe to our stream and let me show you how you can enable button based on input fields values.


  package com.broda.rxjava.rxtutorial;
  
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.widget.Button;
  import android.widget.EditText;
  import android.text.TextUtils;
  import android.widget.Toast;
  import com.jakewharton.rxbinding.view.RxView;
  import com.jakewharton.rxbinding.widget.RxTextView;
  import rx.Observable;

  public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText emailEditTextView = (EditText) findViewById(R.id.emailEditText);
        EditText passwordEditTextView = (EditText) findViewById(R.id.emailPasswordText);
        Button button = (Button) findViewById(R.id.button);
        button.setEnabled(false);

        Observable emailObservable = RxTextView.textChanges(emailEditTextView);
        Observable passwordObservable = RxTextView.textChanges(passwordEditTextView);

        Observable.combineLatest(emailObservable, passwordObservable, (c, c2) -> !TextUtils.isEmpty(c) && !TextUtils.isEmpty(c2))
                .subscribe(button::setEnabled);

        RxView.clicks(button).subscribe(aVoid -> {
            Toast.makeText(MainActivity.this, "Whola!", Toast.LENGTH_SHORT).show();
        });
    }
}  

As you can see I used method reference to make it look even cleaner. I could write it like this

subscribe(aBoolean -> button.setEnabled(aBoolean))

but I prefer this shorter version:

subscribe(button::setEnabled)

Ok! Our button should be enabled once we type something into our fields. Lets implement some onClick listener but in a new way.


  RxView.clicks(button).subscribe(aVoid -> {
            Toast.makeText(MainActivity.this, "Whola!", Toast.LENGTH_SHORT).show();
        });
  It’s all done!

It’s all done! As you can see there is no “new XxxListener” at all, our syntax is clean and expressive. This are just basics of Reactive Programming. I hope you enjoyed this article and that I managed to spark your interest in this topic. In the next article I will show you how to avoid using AsycTasks and how to delegate execution of your code to different Threads.

Please do not hesitate to write your comments or questions below.

Take a free consultation

Get an online consultation or workshop session. Let's estimate costs!