SlideShare a Scribd company logo
1 of 35
Download to read offline
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

What's hot

Clockless design language - ilia greenblat
Clockless design language - ilia greenblatClockless design language - ilia greenblat
Clockless design language - ilia greenblat
chiportal
 
iOS Multithreading
iOS MultithreadingiOS Multithreading
iOS Multithreading
Richa Jain
 
Javascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to JavascriptJavascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to Javascript
Livingston Samuel
 
2010-02-09 Reactor Pattern & Event Driven Programming
2010-02-09 Reactor Pattern & Event Driven Programming2010-02-09 Reactor Pattern & Event Driven Programming
2010-02-09 Reactor Pattern & Event Driven Programming
Lin Jen-Shin
 

What's hot (20)

Java GC
Java GCJava GC
Java GC
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8
 
[Java concurrency]01.thread management
[Java concurrency]01.thread management[Java concurrency]01.thread management
[Java concurrency]01.thread management
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRuby
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
Clockless design language - ilia greenblat
Clockless design language - ilia greenblatClockless design language - ilia greenblat
Clockless design language - ilia greenblat
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrency
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
rx-java-presentation
rx-java-presentationrx-java-presentation
rx-java-presentation
 
The Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on AndroidThe Mayans Lost Guide to RxJava on Android
The Mayans Lost Guide to RxJava on Android
 
Reactive Extensions for JavaScript
Reactive Extensions for JavaScriptReactive Extensions for JavaScript
Reactive Extensions for JavaScript
 
JavaScript Looping Statements
JavaScript Looping StatementsJavaScript Looping Statements
JavaScript Looping Statements
 
iOS Multithreading
iOS MultithreadingiOS Multithreading
iOS Multithreading
 
Node.js System: The Approach
Node.js System: The ApproachNode.js System: The Approach
Node.js System: The Approach
 
RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015
 
Lp seminar
Lp seminarLp seminar
Lp seminar
 
Javascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to JavascriptJavascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to Javascript
 
2010-02-09 Reactor Pattern & Event Driven Programming
2010-02-09 Reactor Pattern & Event Driven Programming2010-02-09 Reactor Pattern & Event Driven Programming
2010-02-09 Reactor Pattern & Event Driven Programming
 
Qt Framework Events Signals Threads
Qt Framework Events Signals ThreadsQt Framework Events Signals Threads
Qt Framework Events Signals Threads
 

Similar to RxJava@DAUG

Glenn Vanderburg — Learning to love JavaScript
Glenn Vanderburg — Learning to love JavaScriptGlenn Vanderburg — Learning to love JavaScript
Glenn Vanderburg — Learning to love JavaScript
atr2006
 

Similar to RxJava@DAUG (20)

RxJava@Android
RxJava@AndroidRxJava@Android
RxJava@Android
 
Reactive programming with rx java
Reactive programming with rx javaReactive programming with rx java
Reactive programming with rx java
 
Rx Swift
Rx SwiftRx Swift
Rx Swift
 
RxJava2 Slides
RxJava2 SlidesRxJava2 Slides
RxJava2 Slides
 
Node.js: CAMTA Presentation
Node.js: CAMTA PresentationNode.js: CAMTA Presentation
Node.js: CAMTA Presentation
 
React native
React nativeReact native
React native
 
Streams
StreamsStreams
Streams
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
Progscon 2017: Taming the wild fronteer - Adventures in Clojurescript
Progscon 2017: Taming the wild fronteer - Adventures in ClojurescriptProgscon 2017: Taming the wild fronteer - Adventures in Clojurescript
Progscon 2017: Taming the wild fronteer - Adventures in Clojurescript
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
 
BASICS OF VERT.X - A toolkit for building asynchronous and reactive app
BASICS OF VERT.X - A toolkit for building asynchronous and reactive appBASICS OF VERT.X - A toolkit for building asynchronous and reactive app
BASICS OF VERT.X - A toolkit for building asynchronous and reactive app
 
Javascript internals
Javascript internalsJavascript internals
Javascript internals
 
DZone_RC_RxJS
DZone_RC_RxJSDZone_RC_RxJS
DZone_RC_RxJS
 
Reactive java - Reactive Programming + RxJava
Reactive java - Reactive Programming + RxJavaReactive java - Reactive Programming + RxJava
Reactive java - Reactive Programming + RxJava
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
RxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android MontréalRxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android Montréal
 
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
ClojureScript - Making Front-End development Fun again - John Stevenson - Cod...
 
End to End Akka Streams / Reactive Streams - from Business to Socket
End to End Akka Streams / Reactive Streams - from Business to SocketEnd to End Akka Streams / Reactive Streams - from Business to Socket
End to End Akka Streams / Reactive Streams - from Business to Socket
 
RxJava 2 Reactive extensions for the JVM
RxJava 2  Reactive extensions for the JVMRxJava 2  Reactive extensions for the JVM
RxJava 2 Reactive extensions for the JVM
 
Glenn Vanderburg — Learning to love JavaScript
Glenn Vanderburg — Learning to love JavaScriptGlenn Vanderburg — Learning to love JavaScript
Glenn Vanderburg — Learning to love JavaScript
 

Recently uploaded

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Recently uploaded (20)

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 

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)