Fatal Exception: java.lang.OutOfMemoryError
OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available
March 16, 2016 | GitHub: ksza / rx_tmjug
The fundamentals of Reactive Streams in Java. A hands on experience
Thinking in Reactive Programming, with examples - RxJava
Reactive Programming
March 16, 2016 | GitHub: ksza / rx_tmjug
- is programming with asynchronous data streams
- anything can be a stream: user inputs, data structures, etc
- a generous toolbox of functions to create, filter & combine streams
March 16, 2016 | GitHub: ksza / rx_tmjug
Why ReactiveX?
ReactiveX is more than an API, it's an idea and a breakthrough in programming. It has inspired several other APIs, frameworks, and even programming languages.
Reactive Revolution
- The Reactive Streams API, heavily influenced by RxJava
- Doug Lea - request to include RS idiom in Java 9
March 16, 2016 | GitHub: ksza / rx_tmjug
Adopting Reactive Programming
The hardest part of the learning journey is thinking in Reactive
... we'll try a kata
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx
- What's Rx
- Exercise: Explore some simple Rx operators
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx
... a Reactive Extension for the JVM
March 16, 2016 | GitHub: ksza / rx_tmjug
The Observer pattern done right
ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern, and functional programming
1. Intro to Rx
- Extends the observer pattern
- Supports sequences of data and/or event
- Compose sequences together declaratively using operators
- Abstracts away: low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx - Simple Observable
obs = Observable.just(1, 2, 3, 4, 5);
obs.subscribe(onNext, onError, onComplete);
1
2
3
4
5
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx - Simple Observable
obs.subscribe(new Action1<Integer>() {
@Override
public void call(Integer value) { /* on emition */ }
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) { /* on error */ }
}, new Action0() {
@Override
public void call() { /* on complete */ }
});
March 16, 2016 | GitHub: ksza / rx_tmjug
Observable.just(1, 2, 3, 4, 5)
.map(new Func1<Integer, String>() {
@Override
public String call(Integer number) {
return number.toString();
}
});
1. Intro to Rx - Map Operator
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx - Map Operator
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx - Filter Operator
(Chaining)
Observable obs = Observable.just(1, 2, 3, 4, 5)
.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer number) {
return number % 2 == 0;
}
})
.map(new Func1<Integer, String>() {
@Override
public String call(Integer number) {
return number.toString();
}
});
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx
March 16, 2016 | GitHub: ksza / rx_tmjug
1. Intro to Rx
- Observables are immutable
- Compose functions into processing chains
- Avoid callback hell
- Structured code, feels like the right way!
March 16, 2016 | GitHub: ksza / rx_tmjug
public void fetchUserDetails() {
// first, request the users...
mService.requestUsers(new Callback<GithubUsersResponse>() {
@Override
public void success(final GithubUsersResponse githubUsersResponse, final Response response) {
// Request Users request completed
final List<GithubUserDetail> githubUserDetails = new ArrayList<GithubUserDetail>();
// next, loop over each item in the response
for (GithubUserDetail githubUserDetail : githubUsersResponse) {
// request a detail object for that user
mService.requestUserDetails(githubUserDetail.mLogin, new Callback<GithubUserDetail>() {
@Override
public void success(GithubUserDetail githubUserDetail, Response response) {
// User Detail request completed for user
githubUserDetails.add(githubUserDetail);
if (githubUserDetails.size() == githubUsersResponse.mGithubUsers.size()) {
// update UI with user details
}
}
@Override
public void failure(RetrofitError error) {
// Request User Detail Failed
}
});
}
}
@Override
public void failure(RetrofitError error) { /* Request User Failed!!!! */ }
});
}
public void rxFetchUserDetails() {
// request the users
mService.rxRequestUsers().concatMap(Observable::from)
.concatMap((GithubUser githubUser) ->
// request the details for each user
mService.rxRequestUserDetails(githubUser.mLogin)
)
// accumulate them as a list
.toList()
// define which threads information will be passed on
.subscribeOn(Schedulers.newThread())
.observeOn(JavaFxScheduler.getInstance())
// post them on an eventbus
.subscribe(githubUserDetails -> { /* update UI with user details */ });
}
Exercise 1: Intro to Rx
git clone git@github.com:ksza/rx_tmjug.git
cd rx_tmjug
git checkout ex1
git checkout -b ex1
- Explore the ExampleUnitTest class
- Rewrite the "testObservable" method using TestSubscriber
March 16, 2016 | GitHub: ksza / rx_tmjug
2. Lambda expression
"... they provide a clear and concise way to represent one method interface using an expression ... "
-- Java 8
March 16, 2016 | GitHub: ksza / rx_tmjug
2. Lambda expression
/* no arguments, single statement */ () -> 42
/* one argument */ number -> number * 2
/* multiple arguments */ (i, j) -> i * j
/* multiple arguments types */ (int i, long j) -> i * j
/* multiple statements */
(int i, long j) -> { long result = i * j; return result; }
March 16, 2016 | GitHub: ksza / rx_tmjug
2. Less code using with lambdas
Observable.just(1, 2, 3, 4, 5)
.map(new Func1<Integer, String>() {
@Override
public String call(Integer number) {
return number.toString();
}
});
becomes
Observable.just(1, 2, 3, 4, 5)
.map(i -> i.toString());
March 16, 2016 | GitHub: ksza / rx_tmjug
2. Lambda expressions - Method Reference
obs = Observable.just("1", "2", "3")
/* lambda enhanced code */
obs.map(nr -> Integer.parseInt(nr))
/* using method reference */
obs.map(Integer::parseInt)
- sometimes, a lambda expression does nothing but call an existing method
March 16, 2016 | GitHub: ksza / rx_tmjug
Exercise 2: Less code with lambdas
Neat huh?! Let's get to work
- Play around with the IDE features to expand/replace lambda expressions
- Write a new test for transforming Integers into Strings
March 16, 2016 | GitHub: ksza / rx_tmjug
Exercise 3: Explore Rx Operators
- Please make all tests in ExploreSimpleOperatorsTest pass using only Rx operators!
- Fix the tests sequentially
March 16, 2016 | GitHub: ksza / rx_tmjug
4. Reactive HTTP with Retrofit
"Retrofit turns your HTTP API into a Java interface"
March 16, 2016 | GitHub: ksza / rx_tmjug
4. Reactive HTTP with Retrofit
public interface OmdbApi {
@GET("/?y=&plot=short&r=json")
Observable<OmdbMovie> findByTitle(@Query("t") String t);
}
...
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.omdbapi.com")
.build();
OmdbApi api = retrofit.create(OmdbApi.class);
March 16, 2016 | GitHub: ksza / rx_tmjug
Exercise 4: Reactive HTTP with Retrofit
git add -A && git commit -m "progress"
git checkout ex2
git checkout -b ex2
- Explore & execute tests for the provided API
March 16, 2016 | GitHub: ksza / rx_tmjug
Exercise 5: Easy networking with reactive streams
- Search movies by title using the api and display results in popup
March 16, 2016 | GitHub: ksza / rx_tmjug
5. Schedulers
- By default, an Observable and the operators, will work on the same thread on which its the subscribe method is called
- subscribeOn: Schedulers.computation(), Schedulers.io(), etc
- observeOn: JavaFxScheduler.getInstance(), etc
March 16, 2016 | GitHub: ksza / rx_tmjug
March 16, 2016 | GitHub: ksza / rx_tmjug
6. Transforming Observables
- RxBinding: Bind to your views and ui events in a reactive way
- Use of flatMap and multithread
git add -A && git commit -m "progress"
git checkout ex3
git checkout -b ex3
March 16, 2016 | GitHub: ksza / rx_tmjug
6. FlatMap
March 16, 2016 | GitHub: ksza / rx_tmjug
Returns an Observable that emits items based on applying a function that you supply to each item emitted by the source Observable, where that function returns an Observable, and then merging those resulting Observables and emitting the results of this merger.
6. FlatMap
March 16, 2016 | GitHub: ksza / rx_tmjug
6. Multithread ?
RxTextView.textChanges(searchText)
.flatMap(title -> omdbApi.searchByTitle(title))
.subscribeOn(Schedulers.io());
RxTextView.textChanges(searchText)
.flatMap(
title -> omdbApi.searchByTitle(title)
.subscribeOn(Schedulers.io())
);
March 16, 2016 | GitHub: ksza / rx_tmjug
6. Unsubscribe
- Fix memory leaks
- Subscription.unsubscribe()
- CompositeSubscription
March 16, 2016 | GitHub: ksza / rx_tmjug
7. Optimal "hot search"
git add -A && git commit -m "progress"
git checkout ex4
git checkout -b ex4
- MovieSerchService#last_title_should_match_search
should pass
March 16, 2016 | GitHub: ksza / rx_tmjug
7. Optimal "hot search"
To improve:
- avoid too many requests
- handle errors
- responses are not ordered
March 16, 2016 | GitHub: ksza / rx_tmjug
7. Limiting throughput
March 16, 2016 | GitHub: ksza / rx_tmjug
7. Handling errors
March 16, 2016 | GitHub: ksza / rx_tmjug
7. Handling errors
March 16, 2016 | GitHub: ksza / rx_tmjug
7. flatMap = merge(map)
- non blocking
- fail fast
March 16, 2016 | GitHub: ksza / rx_tmjug
7. flatMap multithread
March 16, 2016 | GitHub: ksza / rx_tmjug
7. concatMap
- Order is guaranteed
- Blocking!
March 16, 2016 | GitHub: ksza / rx_tmjug
7. concatMap
March 16, 2016 | GitHub: ksza / rx_tmjug
7. switchMap
- Subscribe for the last only
- Unsubscribe/cancel the previous
March 16, 2016 | GitHub: ksza / rx_tmjug
7. switchMap
March 16, 2016 | GitHub: ksza / rx_tmjug
When the Producer is faster than the consumer
March 16, 2016 | GitHub: ksza / rx_tmjug
8. Backpressure
March 16, 2016 | GitHub: ksza / rx_tmjug
8. Backpressure
8. Backpressure
March 16, 2016 | GitHub: ksza / rx_tmjug
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
9. Fetch movie details
ToDo:
- fetch the movie details using OmdbApi#getByTitle
- update the details vie using MovieDetailsView#updateDetails
Thank You!
March 16, 2016 | GitHub: ksza / rx_tmjug
RxJava for tmJug
By Karoly Szanto
RxJava for tmJug
- 403