SlideShare a Scribd company logo
RxJava on Android
2016 Maxim Volgin
mdevcon 2016 takeouts
❖ Out of about 10 technical session, 3 sessions were specifically about
Rx in mobile. In yet another session Rx was mentioned a lot, too.
❖ It seems, that Rx is extremely popular on Android, and is slowly
getting there on iOS (it is sort of related to Swift 3 release date,
because Apple expects to to make language syntax backwards
compatible from Swift 3 onwards).
❖ One of the sessions took it even further: the speaker has shown that
if you build the entire stack from mobile to server in Rx (Swift,
Kotlin, Java, Javascript, C#, etc.), it will improve maintainability, as
the programming language becomes largely irrelevant, Rx reads all
the same in any programming language.
Motivation
(or “lifecycle’s a bitch”)
After a few hard months of development I figured that I do not understand what’s
going on in the app anymore:
❖ current state was virtually impossible to figure out in a reliable way
❖ it was practically impossible to collect all the data required for statistics
❖ some async tasks were fired and some events were propagated via the bus, but due
to that quirky phenomenon known as lifecycle some of the components simply
weren’t alive to receive events
❖ for the same lifecycle reason, callbacks were often called on already dead
components
I desperately needed a way to orchestrate all that mayhem. A way to combine results
of multiple interdependent async calls in a meaningful way and make it available to
components that did not necessarily exist yet at the time when the calls returned.
There were a few frameworks for chaining async calls,
but none to combine their results in time and space.
Until I came across Rx.
It was hard to understand.
It required to change the way of thinking.
It required to learn new building blocks instead of familiar
Android techniques and GoF patterns.
But it was definitely worth it.
…and hey, Retrofit supported it too!
– one colleague from a web/backend project
“Are you mad? It’s just a simple app.”
The ‘simple app’ happened to be
the biggest consumer of our API’s.
Theory: Rx and FRP
❖ Reactive (i.e. push vs pull/poll) concept is not new: Java
had java.util.Observable class since the very beginning,
Apple had KVO since at least OS X.
❖ Rx is not really FP, because even though it does draw a
lot from FP, it is mostly concerned with so-called “side
effects”, which are considered an edge-case in FP.
❖ Rx can be rather defined as reactive programming with
(asynchronous) data streams. For all practical purposes,
Rx Observable can be seen as a “push-iterator”.
What is an Observable
❖ The design patterns Rx is build around are Iterator and
Observable/Observer. Observable can emit so many  (0..n) items by
invoking 'onNext' method on Observer, and then call 'onComplete'
or 'onError'. So basically, observables (asynchronously) emit
sequences of items that can be filtered/transformed/combined in
many ways. On so-called 'marble diagrams' emitted items are
represented by marbles (O), errors by crosses (X) and completion
by vertical dashes (|), for example: —O—O——O—X—|—>. 
❖ There are also degenerate (limiting) cases of Observable: Single
and Completable. Whereas and Observable has 0..n elements,
Single has only one, and Completable has none at all.
Tradeoffs
(or: “don’t lose your marbles”)
The best way of understanding Rx is looking at so-called
marble diagrams.
Here’s an awesome resource, describing most building
blocks of Rx -
http://rxmarbles.com/
Threading, Hot & Cold
❖ Observable can be subscribed and observed on different threads.
Observable will run its code on subscribe-thread, and call Observer
on observe-thread. By default, everything runs on the current
thread. For Android, a special main thread is available.
❖ There are cold and hot Observables: cold ones start emitting items
only when subscribed to, hot ones are independent; a special case
of Observable is ConnectableObservable, it starts emitting items
only when 'connect()' method is called on it, which allows to
subscribe more than one subscriber and be sure that they all receive
the same items. a regular Observable can be made
ConnectableObservable by invoking '.publish()' method on it.
Sharing cold observables
❖ Hot observables (such as user input) produce events on
their own, making multiple subscriptions to them poses
no problem.
❖ Cold observables, which actually start executing their
code only upon subscription, need to be told to wait until
all subscribers have subscribed. This can be achieved by
converting them to ConnectableObservable’s:
final ConnectableObservable<Integer> connectableObservable = observable.publish();

shared.subscribe(subscriber1);

shared.subscribe(subscriber2);

shared.connect();
Subject are both Observables and Subscribers
❖A combination of Observable and Observer is called Subject.
❖Different subject can be used for their special behaviors, for example
BehaviorSubject always keeps its last item cached for new subscribers and
is therefore very useful for all sorts of UI subscribers that need the latest
state.
❖ PublishSubject and BehaviorSubject proved to be the most useful in my
experience.
❖ Though I also found some use for ReplaySubject too:
private final ReplaySubject<Timestamped<Request>> requestReplaySubject =
ReplaySubject.createWithTimeAndSize(MAX_CACHED_REQUEST_AGE_IN_SECONDS, TimeUnit.SECONDS, MAX_REQUEST_CACHE_SIZE,
Schedulers.immediate());
How to subscribe
❖ It is possible to subscribe to Observable with Action1,
Observer or Subscriber; with Action1, you must handle
onNext/onComplete/onError in separate actions;
Observer can (and should) handle all three; Subscriber is
the same as Observer, but it keeps reference to its own
subscription and therefore can unsubscribe whenever it is
needed.
❖ .materialize() wraps all events (i.e. onNext/onError/
onCompleted) into Notification and only emits
onNext(Notification<>), so Action1 will suffice.
How to create an Observable
❖ It is highly unlikely that you will ever need to create an Observable manually -
❖ first of all, because they have a strict contract which is rather hard to implement properly,
❖ but most importantly because there are plenty of simpler ways of making one, such as
static factory methods of Observable class:
❖ .just(), .from(), .range(), .empty(), .error(), .fromCallable(), …
❖ To create an Observable from a value (or several values), use 'just()'; to create if from a
collection or array, use 'from()'; NB: if you use 'just()' on collection/array, your Observable
will emit only 1 item, this collection/array as a whole; if you use 'from()' on collection/
array, your Observable will emit contents of collection/array as separate items.
❖ Also, you can concatenate Observables with .concatWith()
❖ Also, since Subjects are also in part Observables, every concrete Subject class has a static
factory method .create()
RxJava
❖ available on Android
❖ looks scary in pre-Java8 syntax
– Captain Obvious
“You’re gonna need RxJava lib.”
…and
You will also need
RxAndroid lib
…for 1 method only:
AndroidSchedulers.mainThr
ead()
The purpose
❖ Primary practical purpose of Rx on Android for me: it
solves so-called “callback hell" (with nested callbacks).
❖ Rx allows to combine results, but it can also split and
then combine again, i.e. you can derive several
Observables from one, append different processing to
them, combine their results and execute as a whole only
once (useful for some cases of data enrichment).
❖ Reactive means paradigm shift from pull/poll to push,
which is a major relief on a mobile platform.
What is easy
❖ easy to solve threading issues: .subscribeOn(), .observeOn()
❖ easy to solve “too many events” issues: .sample(), .throttle(), .debounce()
❖ easy to combine multiple asynchronous data streams: .zip(), .combineLatest()
❖ easy to split one data stream, process it in different ways, and possibly combine
again afterwards (useful in some data enrichment scenarios)
❖ easy to implement retry/fallback scenarios: .onErrorResume(),
onErrorNext(), .retry([so many times]), etc.
❖ easy to enforce timeout: .timeout()
❖ easy to timestamp events or measure time intervals between
them: .timestamp(), .interval()
Too many events: .sample(), .throttleFirst(), .debounce()
❖ This situation often happens in user input processing,
such as drag, scroll, etc.
❖ .throttle…() and .debounce() handle this situation
automatically
❖ .sample() allows to control it manually:
final PublishSubject<Void> sampler = PublishSubject.create();

final Subscription subscription = events.sample(sampler).subscribe(new Action1<Integer>() { // …

Feel the power
❖ Obviously, you would expect to find the basic FP toolset
of .filter(), .map(), .reduce(), .flatMap(), and such. But Rx does not stop there.
❖ .scan()
final List<String> simple = Observable.<String>just("a", "b", "c", "d", "e", "f").scan("_", new Func2<String, String, String>() {

@Override

public String call(String lhs, String rhs) {

return lhs + rhs;

}

}).toList().toBlocking().single(); // [_, _a, _ab, _abc, _abcd, _abcde, _abcdef]
❖ .collect():
final String result = Observable.<Integer>range(1, 5).collect(new Func0<StringBuilder>() {

@Override

public StringBuilder call() {

return new StringBuilder();

}

}, new Action2<StringBuilder, Integer>() {

@Override

public void call(StringBuilder stringBuilder, Integer integer) {

stringBuilder.append(String.format("%s, ", integer));

}

}).map(new Func1<StringBuilder, String>() {

@Override

public String call(StringBuilder stringBuilder) {

return stringBuilder.toString();

}

}).toBlocking().single(); // 1, 2, 3, 4, 5,
.zip() and .combineLatest()
❖ There are plenty of ways of combining data streams
(items emitted by Observables); for instance
'combineLatest()' method emits a combined item
whenever any of the source Observables emits an item
(last values of other sources are taken from cache); 'zip()'
method emits a combined item whenever all source
Observables emitted a new item, therefore the name (it
works like a zipper); to assign indexes to items emitted by
an Observable, one can 'zip' it with an infinite Iterable
producing integer numbers (by using 'zipWith()' method).
How to number events
public class RxIndex {
    private static class InfiniteIterator implements Iterator<Integer> {
        private int index = 0;
        @Override
        public boolean hasNext() {
            return true;
        }
        @Override
        public Integer next() {
            return index++;
        }
        @Override
        public void remove() {
        }
    }
    private static class InfiniteIterable implements Iterable<Integer> {
        private final Iterator<Integer> iterator = new InfiniteIterator();
        @Override
        public Iterator<Integer> iterator() {
            return iterator;
        }
    }
    public static <T> Observable<Indexed<T>> zipWithIndex(final Observable<T> values) {
        return values.zipWith(new InfiniteIterable(), new Func2<T, Integer, Indexed<T>>() {
            @Override
            public Indexed<T> call(T value, Integer index) {
                return new Indexed<T>(value, index);
            }
        });
    }
}
.merge(), .map(), .flatMap() and .concatMap()
❖ If you need to merge items emitted by multiple
Observables in the order of appearance, use 'merge()'
method.
❖ If you have an Observable emitting collections of items,
and you want to combine all those collections into one,
use 'flatMap()'; if it is done asynchronously and you
need to ensure the order of items, use 'concatMap()'
instead.
.defer()
❖ Obviously, once an Observable did emit all its items, it
becomes empty, so subscribing again will not give any
result; if we need that it does its work again every time,
we can use factory method 'defer()', it makes sure that it
is always a new instance of Observable for every
subscription (this is useful for service calls and such).
.toList() and .take(1)
❖ It is more convenient to return series of values as an
Observable from value type; The benefit of doing it so is
that you can simply add '.toList()' to receive all values at
once or '.take(1)' to receive only first value (if available).
Typical Rx error messages
❖ Make sure errors are handled either in Subscribers or in
onError() methods, otherwise you will
get OnErrorNotImplementedException.
❖ Always specify backpressure policy, such as
‘onBackpressureDrop()', when you expect many events
which might not be processed instantly, otherwise you
will get a MissingBackpressureException.
Dealing with errors
❖ First of all, you can always add thread and stack trace logging
in .doOnNext(), or anywhere for that matter.
❖ Secondly, you can use a special overload of .flatMap() which takes 3
parameters for onNext/onError/onCompleted respectively to propagate
errors and completion of the top-level observable to the result:
❖ Thirdly, you can use .materialize() to produce Notification wrapper for any
kind of event (i.e. onNext/onError/onCompleted). This can be particular
useful to store last status of some server request (such as an authentication
attempt).
public final <R> Observable<R> flatMap(

Func1<? super T, ? extends Observable<? extends R>> onNext,

Func1<? super Throwable, ? extends Observable<? extends R>> onError,

Func0<? extends Observable<? extends R>> onCompleted) {

return merge(mapNotification(onNext, onError, onCompleted));
private static void initDebugLoggingForSwallowedExceptions() {

final RxJavaPlugins rxJavaPlugins = RxJavaPlugins.getInstance();

rxJavaPlugins.registerErrorHandler(new RxErrorHandler());

rxJavaPlugins.registerObservableExecutionHook(new RxObservableExecutionHook());

}
Error- and Execution hooks
❖ Finding the source of errors and following actual flow of
Rx processing can prove difficult. There is a remedy
though:
public class RxErrorHandler extends RxJavaErrorHandler {



@Override

public void handleError(Throwable t) {

final Thread thread = Thread.currentThread();

final String threadInfo = String.format("[thread: #%d '%s']", thread.getId(), thread.getName());

Log.d(threadInfo);

Log.d(t);

}
Execution hook contd.
public class RxObservableExecutionHook extends RxJavaObservableExecutionHook {

@Override

public <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> f) {

@Override

public <T> Observable.OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance,
Observable.OnSubscribe<T> onSubscribe) {

@Override

public <T> Subscription onSubscribeReturn(Subscription subscription) {

@Override

public <T, R> Observable.Operator<? extends R, ? super T> onLift(Observable.Operator<? extends R, ? super T> lift) {

@Override
public <T> java.lang.Throwable onSubscribeError(java.lang.Throwable e) {

Log.d(logEntryWithStack(String.format("%s", e.getMessage())));

return super.onSubscribeError(e);

}

public static String logEntryWithStack(final String firstLine) {

final Thread thread = Thread.currentThread();

final String threadInfo = String.format("[thread: #%d '%s']", thread.getId(), thread.getName());

final Observable<String> lines = Observable.from(thread.getStackTrace()).filter(new Func1<StackTraceElement,
Boolean>() {

@Override

public Boolean call(StackTraceElement stackTraceElement) {

final String className = stackTraceElement.getClassName();

return (className.startsWith(PACKAGE) && !className.contains("_") && !
className.endsWith(RxObservableExecutionHook.class.getName()));

}

}).map(new Func1<StackTraceElement, String>() {

@Override

public String call(StackTraceElement stackTraceElement) {

return String.format("%s.%s() %s:%d", stackTraceElement.getClassName(),
stackTraceElement.getMethodName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber());

}

}).startWith(firstLine, threadInfo);
Thread safety and memory concerns
❖ According to the contract, Observable code must produce all events on
the same thread. This rule is easily broken by calling Subjects’ .onNext()
method from different threads. How to cope? Use . serialized() which
ensures that contract is met:
❖ Be careful with operators such as .distinct(),
prefer .distinctUntilChanged()
❖ Prevent memory leaks by keeping connections in
CombinedSubscriptions or use Subscribers (which can unsubscribe
themselves):
subject.asObservable().serialized();
final CompositeSubscription compositeSubscription = new CompositeSubscription();

compositeSubscription.add(subscription);

Testing, and other special cases
❖ For testing, you have TestScheduler to manually control virtual time and
TestSubscriber with all kinds of asserts defined in it.
❖ When synchronicity and reactiveness is not what you are testing,
use .toBlocking()
❖ .toBlocking() kills all reactiveness and converts an Observable to a plain
value, so it kind of defeats the whole idea of Rx. However, besides tests, it
might prove useful in all sorts of handlers and interceptors that are
expected to block further processing on their thread.
❖ .materialize() can be used to process any outcome (i.e. also error or premature
completion) as valid outcome. Besides tests, it can come in handy when you
want to keep the specific error for future reference, such as in login scenario.
Gains
(or “combine and rule”)
❖ easy to combine results of several async calls in time and
space
❖ easy to maintain and propagate state
❖ easy to skip events or wait for a certain condition to occur
❖ easy to process input forms
❖ easy to process click/scroll events
❖ lifecycle is not an issue anymore
More to explore
❖ A brand new O’Reilly book “Reactive programming with RxJava” by Tomasz
Nurkiewicz & Ben Christensen
❖ Rx JavaDoc: http://reactivex.io/RxJava/javadoc/overview-summary.html
❖ Rx marble diagrams: http://rxmarbles.com/
❖ “The introduction to Reactive Programming you've been missing by André
Staltz”: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
❖ an awesome GOTO presentation “Going Reactive, An Android Architectural
Journey by Matthias Käppler” - https://www.youtube.com/watch?
v=R16OHcZJTno
❖ My own playground at GitHub - https://github.com/maxvol/
RxJavaPlayground (feel free to mess it up)

More Related Content

PPTX
Fork Join
PPT
An Introduction to JVM Internals and Garbage Collection in Java
KEY
Automatic Reference Counting
PDF
JavaScript for real men
KEY
Modern Java Concurrency
PDF
Java Concurrency in Practice
KEY
Grand Central Dispatch Design Patterns
PPTX
Fork Join
An Introduction to JVM Internals and Garbage Collection in Java
Automatic Reference Counting
JavaScript for real men
Modern Java Concurrency
Java Concurrency in Practice
Grand Central Dispatch Design Patterns

What's hot (20)

PPTX
Java GC
PDF
Working With Concurrency In Java 8
PDF
[Java concurrency]01.thread management
PDF
Connecting the Worlds of Java and Ruby with JRuby
PDF
RxJava on Android
PPT
Clockless design language - ilia greenblat
PDF
Introduction to RxJS
PPTX
Effective java - concurrency
PDF
Java Concurrency Gotchas
PDF
rx-java-presentation
PDF
The Mayans Lost Guide to RxJava on Android
PPTX
Reactive Extensions for JavaScript
PDF
JavaScript Looping Statements
PPT
iOS Multithreading
PPTX
Node.js System: The Approach
PPTX
RxJS and Reactive Programming - Modern Web UI - May 2015
PPT
Lp seminar
PPTX
Javascript session 01 - Introduction to Javascript
PDF
2010-02-09 Reactor Pattern & Event Driven Programming
PPTX
Qt Framework Events Signals Threads
Java GC
Working With Concurrency In Java 8
[Java concurrency]01.thread management
Connecting the Worlds of Java and Ruby with JRuby
RxJava on Android
Clockless design language - ilia greenblat
Introduction to RxJS
Effective java - concurrency
Java Concurrency Gotchas
rx-java-presentation
The Mayans Lost Guide to RxJava on Android
Reactive Extensions for JavaScript
JavaScript Looping Statements
iOS Multithreading
Node.js System: The Approach
RxJS and Reactive Programming - Modern Web UI - May 2015
Lp seminar
Javascript session 01 - Introduction to Javascript
2010-02-09 Reactor Pattern & Event Driven Programming
Qt Framework Events Signals Threads
Ad

Similar to RxJava@DAUG (20)

PDF
RxJava@Android
PDF
RxJava pour Android : présentation lors du GDG Android Montréal
PPTX
Intro to Functional Programming with RxJava
PPTX
Introduction to RxJava on Android
PDF
Reactive programming on Android
PDF
Sperasoft Talks: RxJava Functional Reactive Programming on Android
PPTX
Reactive Programming on Android - RxAndroid - RxJava
PDF
Streamlining with rx
PPTX
Intro to Reactive Thinking and RxJava 2
PDF
Practical RxJava for Android
PDF
Reactive Functional Programming with Java 8 on Android N
PDF
Reactive programming on Android
PDF
Practical RxJava for Android
PPTX
Reactive programming with RxAndroid
PPTX
Rxandroid
PPTX
RxAndroid
PDF
Streams, Streams Everywhere! An Introduction to Rx
PPTX
RxJava2 Slides
PDF
RxJS - The Reactive extensions for JavaScript
PPTX
Reactive programming with rx java
RxJava@Android
RxJava pour Android : présentation lors du GDG Android Montréal
Intro to Functional Programming with RxJava
Introduction to RxJava on Android
Reactive programming on Android
Sperasoft Talks: RxJava Functional Reactive Programming on Android
Reactive Programming on Android - RxAndroid - RxJava
Streamlining with rx
Intro to Reactive Thinking and RxJava 2
Practical RxJava for Android
Reactive Functional Programming with Java 8 on Android N
Reactive programming on Android
Practical RxJava for Android
Reactive programming with RxAndroid
Rxandroid
RxAndroid
Streams, Streams Everywhere! An Introduction to Rx
RxJava2 Slides
RxJS - The Reactive extensions for JavaScript
Reactive programming with rx java
Ad

Recently uploaded (20)

PDF
Cost to Outsource Software Development in 2025
PDF
Designing Intelligence for the Shop Floor.pdf
PPTX
L1 - Introduction to python Backend.pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Transform Your Business with a Software ERP System
PDF
17 Powerful Integrations Your Next-Gen MLM Software Needs
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
PPTX
assetexplorer- product-overview - presentation
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Computer Software and OS of computer science of grade 11.pptx
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
Cost to Outsource Software Development in 2025
Designing Intelligence for the Shop Floor.pdf
L1 - Introduction to python Backend.pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Salesforce Agentforce AI Implementation.pdf
Transform Your Business with a Software ERP System
17 Powerful Integrations Your Next-Gen MLM Software Needs
Operating system designcfffgfgggggggvggggggggg
CCleaner Pro 6.38.11537 Crack Final Latest Version 2025
assetexplorer- product-overview - presentation
Oracle Fusion HCM Cloud Demo for Beginners
How to Choose the Right IT Partner for Your Business in Malaysia
wealthsignaloriginal-com-DS-text-... (1).pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
Computer Software and OS of computer science of grade 11.pptx
iTop VPN Free 5.6.0.5262 Crack latest version 2025
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Advanced SystemCare Ultimate Crack + Portable (2025)

RxJava@DAUG

  • 1. RxJava on Android 2016 Maxim Volgin
  • 2. mdevcon 2016 takeouts ❖ Out of about 10 technical session, 3 sessions were specifically about Rx in mobile. In yet another session Rx was mentioned a lot, too. ❖ It seems, that Rx is extremely popular on Android, and is slowly getting there on iOS (it is sort of related to Swift 3 release date, because Apple expects to to make language syntax backwards compatible from Swift 3 onwards). ❖ One of the sessions took it even further: the speaker has shown that if you build the entire stack from mobile to server in Rx (Swift, Kotlin, Java, Javascript, C#, etc.), it will improve maintainability, as the programming language becomes largely irrelevant, Rx reads all the same in any programming language.
  • 3. Motivation (or “lifecycle’s a bitch”) After a few hard months of development I figured that I do not understand what’s going on in the app anymore: ❖ current state was virtually impossible to figure out in a reliable way ❖ it was practically impossible to collect all the data required for statistics ❖ some async tasks were fired and some events were propagated via the bus, but due to that quirky phenomenon known as lifecycle some of the components simply weren’t alive to receive events ❖ for the same lifecycle reason, callbacks were often called on already dead components I desperately needed a way to orchestrate all that mayhem. A way to combine results of multiple interdependent async calls in a meaningful way and make it available to components that did not necessarily exist yet at the time when the calls returned.
  • 4. There were a few frameworks for chaining async calls, but none to combine their results in time and space. Until I came across Rx.
  • 5. It was hard to understand. It required to change the way of thinking. It required to learn new building blocks instead of familiar Android techniques and GoF patterns. But it was definitely worth it. …and hey, Retrofit supported it too!
  • 6. – one colleague from a web/backend project “Are you mad? It’s just a simple app.”
  • 7. The ‘simple app’ happened to be the biggest consumer of our API’s.
  • 8. Theory: Rx and FRP ❖ Reactive (i.e. push vs pull/poll) concept is not new: Java had java.util.Observable class since the very beginning, Apple had KVO since at least OS X. ❖ Rx is not really FP, because even though it does draw a lot from FP, it is mostly concerned with so-called “side effects”, which are considered an edge-case in FP. ❖ Rx can be rather defined as reactive programming with (asynchronous) data streams. For all practical purposes, Rx Observable can be seen as a “push-iterator”.
  • 9. What is an Observable ❖ The design patterns Rx is build around are Iterator and Observable/Observer. Observable can emit so many  (0..n) items by invoking 'onNext' method on Observer, and then call 'onComplete' or 'onError'. So basically, observables (asynchronously) emit sequences of items that can be filtered/transformed/combined in many ways. On so-called 'marble diagrams' emitted items are represented by marbles (O), errors by crosses (X) and completion by vertical dashes (|), for example: —O—O——O—X—|—>.  ❖ There are also degenerate (limiting) cases of Observable: Single and Completable. Whereas and Observable has 0..n elements, Single has only one, and Completable has none at all.
  • 10. Tradeoffs (or: “don’t lose your marbles”) The best way of understanding Rx is looking at so-called marble diagrams. Here’s an awesome resource, describing most building blocks of Rx - http://rxmarbles.com/
  • 11. Threading, Hot & Cold ❖ Observable can be subscribed and observed on different threads. Observable will run its code on subscribe-thread, and call Observer on observe-thread. By default, everything runs on the current thread. For Android, a special main thread is available. ❖ There are cold and hot Observables: cold ones start emitting items only when subscribed to, hot ones are independent; a special case of Observable is ConnectableObservable, it starts emitting items only when 'connect()' method is called on it, which allows to subscribe more than one subscriber and be sure that they all receive the same items. a regular Observable can be made ConnectableObservable by invoking '.publish()' method on it.
  • 12. Sharing cold observables ❖ Hot observables (such as user input) produce events on their own, making multiple subscriptions to them poses no problem. ❖ Cold observables, which actually start executing their code only upon subscription, need to be told to wait until all subscribers have subscribed. This can be achieved by converting them to ConnectableObservable’s: final ConnectableObservable<Integer> connectableObservable = observable.publish();
 shared.subscribe(subscriber1);
 shared.subscribe(subscriber2);
 shared.connect();
  • 13. Subject are both Observables and Subscribers ❖A combination of Observable and Observer is called Subject. ❖Different subject can be used for their special behaviors, for example BehaviorSubject always keeps its last item cached for new subscribers and is therefore very useful for all sorts of UI subscribers that need the latest state. ❖ PublishSubject and BehaviorSubject proved to be the most useful in my experience. ❖ Though I also found some use for ReplaySubject too: private final ReplaySubject<Timestamped<Request>> requestReplaySubject = ReplaySubject.createWithTimeAndSize(MAX_CACHED_REQUEST_AGE_IN_SECONDS, TimeUnit.SECONDS, MAX_REQUEST_CACHE_SIZE, Schedulers.immediate());
  • 14. How to subscribe ❖ It is possible to subscribe to Observable with Action1, Observer or Subscriber; with Action1, you must handle onNext/onComplete/onError in separate actions; Observer can (and should) handle all three; Subscriber is the same as Observer, but it keeps reference to its own subscription and therefore can unsubscribe whenever it is needed. ❖ .materialize() wraps all events (i.e. onNext/onError/ onCompleted) into Notification and only emits onNext(Notification<>), so Action1 will suffice.
  • 15. How to create an Observable ❖ It is highly unlikely that you will ever need to create an Observable manually - ❖ first of all, because they have a strict contract which is rather hard to implement properly, ❖ but most importantly because there are plenty of simpler ways of making one, such as static factory methods of Observable class: ❖ .just(), .from(), .range(), .empty(), .error(), .fromCallable(), … ❖ To create an Observable from a value (or several values), use 'just()'; to create if from a collection or array, use 'from()'; NB: if you use 'just()' on collection/array, your Observable will emit only 1 item, this collection/array as a whole; if you use 'from()' on collection/ array, your Observable will emit contents of collection/array as separate items. ❖ Also, you can concatenate Observables with .concatWith() ❖ Also, since Subjects are also in part Observables, every concrete Subject class has a static factory method .create()
  • 16. RxJava ❖ available on Android ❖ looks scary in pre-Java8 syntax
  • 17. – Captain Obvious “You’re gonna need RxJava lib.”
  • 18. …and You will also need RxAndroid lib …for 1 method only: AndroidSchedulers.mainThr ead()
  • 19. The purpose ❖ Primary practical purpose of Rx on Android for me: it solves so-called “callback hell" (with nested callbacks). ❖ Rx allows to combine results, but it can also split and then combine again, i.e. you can derive several Observables from one, append different processing to them, combine their results and execute as a whole only once (useful for some cases of data enrichment). ❖ Reactive means paradigm shift from pull/poll to push, which is a major relief on a mobile platform.
  • 20. What is easy ❖ easy to solve threading issues: .subscribeOn(), .observeOn() ❖ easy to solve “too many events” issues: .sample(), .throttle(), .debounce() ❖ easy to combine multiple asynchronous data streams: .zip(), .combineLatest() ❖ easy to split one data stream, process it in different ways, and possibly combine again afterwards (useful in some data enrichment scenarios) ❖ easy to implement retry/fallback scenarios: .onErrorResume(), onErrorNext(), .retry([so many times]), etc. ❖ easy to enforce timeout: .timeout() ❖ easy to timestamp events or measure time intervals between them: .timestamp(), .interval()
  • 21. Too many events: .sample(), .throttleFirst(), .debounce() ❖ This situation often happens in user input processing, such as drag, scroll, etc. ❖ .throttle…() and .debounce() handle this situation automatically ❖ .sample() allows to control it manually: final PublishSubject<Void> sampler = PublishSubject.create();
 final Subscription subscription = events.sample(sampler).subscribe(new Action1<Integer>() { // …

  • 22. Feel the power ❖ Obviously, you would expect to find the basic FP toolset of .filter(), .map(), .reduce(), .flatMap(), and such. But Rx does not stop there. ❖ .scan() final List<String> simple = Observable.<String>just("a", "b", "c", "d", "e", "f").scan("_", new Func2<String, String, String>() {
 @Override
 public String call(String lhs, String rhs) {
 return lhs + rhs;
 }
 }).toList().toBlocking().single(); // [_, _a, _ab, _abc, _abcd, _abcde, _abcdef] ❖ .collect(): final String result = Observable.<Integer>range(1, 5).collect(new Func0<StringBuilder>() {
 @Override
 public StringBuilder call() {
 return new StringBuilder();
 }
 }, new Action2<StringBuilder, Integer>() {
 @Override
 public void call(StringBuilder stringBuilder, Integer integer) {
 stringBuilder.append(String.format("%s, ", integer));
 }
 }).map(new Func1<StringBuilder, String>() {
 @Override
 public String call(StringBuilder stringBuilder) {
 return stringBuilder.toString();
 }
 }).toBlocking().single(); // 1, 2, 3, 4, 5,
  • 23. .zip() and .combineLatest() ❖ There are plenty of ways of combining data streams (items emitted by Observables); for instance 'combineLatest()' method emits a combined item whenever any of the source Observables emits an item (last values of other sources are taken from cache); 'zip()' method emits a combined item whenever all source Observables emitted a new item, therefore the name (it works like a zipper); to assign indexes to items emitted by an Observable, one can 'zip' it with an infinite Iterable producing integer numbers (by using 'zipWith()' method).
  • 24. How to number events public class RxIndex {     private static class InfiniteIterator implements Iterator<Integer> {         private int index = 0;         @Override         public boolean hasNext() {             return true;         }         @Override         public Integer next() {             return index++;         }         @Override         public void remove() {         }     }     private static class InfiniteIterable implements Iterable<Integer> {         private final Iterator<Integer> iterator = new InfiniteIterator();         @Override         public Iterator<Integer> iterator() {             return iterator;         }     }     public static <T> Observable<Indexed<T>> zipWithIndex(final Observable<T> values) {         return values.zipWith(new InfiniteIterable(), new Func2<T, Integer, Indexed<T>>() {             @Override             public Indexed<T> call(T value, Integer index) {                 return new Indexed<T>(value, index);             }         });     } }
  • 25. .merge(), .map(), .flatMap() and .concatMap() ❖ If you need to merge items emitted by multiple Observables in the order of appearance, use 'merge()' method. ❖ If you have an Observable emitting collections of items, and you want to combine all those collections into one, use 'flatMap()'; if it is done asynchronously and you need to ensure the order of items, use 'concatMap()' instead.
  • 26. .defer() ❖ Obviously, once an Observable did emit all its items, it becomes empty, so subscribing again will not give any result; if we need that it does its work again every time, we can use factory method 'defer()', it makes sure that it is always a new instance of Observable for every subscription (this is useful for service calls and such).
  • 27. .toList() and .take(1) ❖ It is more convenient to return series of values as an Observable from value type; The benefit of doing it so is that you can simply add '.toList()' to receive all values at once or '.take(1)' to receive only first value (if available).
  • 28. Typical Rx error messages ❖ Make sure errors are handled either in Subscribers or in onError() methods, otherwise you will get OnErrorNotImplementedException. ❖ Always specify backpressure policy, such as ‘onBackpressureDrop()', when you expect many events which might not be processed instantly, otherwise you will get a MissingBackpressureException.
  • 29. Dealing with errors ❖ First of all, you can always add thread and stack trace logging in .doOnNext(), or anywhere for that matter. ❖ Secondly, you can use a special overload of .flatMap() which takes 3 parameters for onNext/onError/onCompleted respectively to propagate errors and completion of the top-level observable to the result: ❖ Thirdly, you can use .materialize() to produce Notification wrapper for any kind of event (i.e. onNext/onError/onCompleted). This can be particular useful to store last status of some server request (such as an authentication attempt). public final <R> Observable<R> flatMap(
 Func1<? super T, ? extends Observable<? extends R>> onNext,
 Func1<? super Throwable, ? extends Observable<? extends R>> onError,
 Func0<? extends Observable<? extends R>> onCompleted) {
 return merge(mapNotification(onNext, onError, onCompleted));
  • 30. private static void initDebugLoggingForSwallowedExceptions() {
 final RxJavaPlugins rxJavaPlugins = RxJavaPlugins.getInstance();
 rxJavaPlugins.registerErrorHandler(new RxErrorHandler());
 rxJavaPlugins.registerObservableExecutionHook(new RxObservableExecutionHook());
 } Error- and Execution hooks ❖ Finding the source of errors and following actual flow of Rx processing can prove difficult. There is a remedy though: public class RxErrorHandler extends RxJavaErrorHandler {
 
 @Override
 public void handleError(Throwable t) {
 final Thread thread = Thread.currentThread();
 final String threadInfo = String.format("[thread: #%d '%s']", thread.getId(), thread.getName());
 Log.d(threadInfo);
 Log.d(t);
 }
  • 31. Execution hook contd. public class RxObservableExecutionHook extends RxJavaObservableExecutionHook {
 @Override
 public <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> f) {
 @Override
 public <T> Observable.OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance, Observable.OnSubscribe<T> onSubscribe) {
 @Override
 public <T> Subscription onSubscribeReturn(Subscription subscription) {
 @Override
 public <T, R> Observable.Operator<? extends R, ? super T> onLift(Observable.Operator<? extends R, ? super T> lift) {
 @Override public <T> java.lang.Throwable onSubscribeError(java.lang.Throwable e) {
 Log.d(logEntryWithStack(String.format("%s", e.getMessage())));
 return super.onSubscribeError(e);
 }
 public static String logEntryWithStack(final String firstLine) {
 final Thread thread = Thread.currentThread();
 final String threadInfo = String.format("[thread: #%d '%s']", thread.getId(), thread.getName());
 final Observable<String> lines = Observable.from(thread.getStackTrace()).filter(new Func1<StackTraceElement, Boolean>() {
 @Override
 public Boolean call(StackTraceElement stackTraceElement) {
 final String className = stackTraceElement.getClassName();
 return (className.startsWith(PACKAGE) && !className.contains("_") && ! className.endsWith(RxObservableExecutionHook.class.getName()));
 }
 }).map(new Func1<StackTraceElement, String>() {
 @Override
 public String call(StackTraceElement stackTraceElement) {
 return String.format("%s.%s() %s:%d", stackTraceElement.getClassName(), stackTraceElement.getMethodName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber());
 }
 }).startWith(firstLine, threadInfo);
  • 32. Thread safety and memory concerns ❖ According to the contract, Observable code must produce all events on the same thread. This rule is easily broken by calling Subjects’ .onNext() method from different threads. How to cope? Use . serialized() which ensures that contract is met: ❖ Be careful with operators such as .distinct(), prefer .distinctUntilChanged() ❖ Prevent memory leaks by keeping connections in CombinedSubscriptions or use Subscribers (which can unsubscribe themselves): subject.asObservable().serialized(); final CompositeSubscription compositeSubscription = new CompositeSubscription();
 compositeSubscription.add(subscription);

  • 33. Testing, and other special cases ❖ For testing, you have TestScheduler to manually control virtual time and TestSubscriber with all kinds of asserts defined in it. ❖ When synchronicity and reactiveness is not what you are testing, use .toBlocking() ❖ .toBlocking() kills all reactiveness and converts an Observable to a plain value, so it kind of defeats the whole idea of Rx. However, besides tests, it might prove useful in all sorts of handlers and interceptors that are expected to block further processing on their thread. ❖ .materialize() can be used to process any outcome (i.e. also error or premature completion) as valid outcome. Besides tests, it can come in handy when you want to keep the specific error for future reference, such as in login scenario.
  • 34. Gains (or “combine and rule”) ❖ easy to combine results of several async calls in time and space ❖ easy to maintain and propagate state ❖ easy to skip events or wait for a certain condition to occur ❖ easy to process input forms ❖ easy to process click/scroll events ❖ lifecycle is not an issue anymore
  • 35. More to explore ❖ A brand new O’Reilly book “Reactive programming with RxJava” by Tomasz Nurkiewicz & Ben Christensen ❖ Rx JavaDoc: http://reactivex.io/RxJava/javadoc/overview-summary.html ❖ Rx marble diagrams: http://rxmarbles.com/ ❖ “The introduction to Reactive Programming you've been missing by André Staltz”: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 ❖ an awesome GOTO presentation “Going Reactive, An Android Architectural Journey by Matthias Käppler” - https://www.youtube.com/watch? v=R16OHcZJTno ❖ My own playground at GitHub - https://github.com/maxvol/ RxJavaPlayground (feel free to mess it up)