Rx.Android
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx
- What's Rx
- Exercise 1: Explore some simple Rx operators
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx
The Observer pattern done right
ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern,
and functional programming
-- http://reactivex.io/
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Aysnc/Push Iterator
single items | multiple items | |
---|---|---|
synchronous | T getData() | Iterable<T> getData() |
asynchronous | Future<T> getData() | Observable<T> getData() |
event | Iterable (pull) | Observable (push) |
---|---|---|
retrieve data | T next() | onNext(T) |
discover error | throws Exception | onError(Exception) |
complete | !hasNext() | onCompleted() |
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx - Simple Observable
obs = Observable.just(1, 2, 3, 4, 5);
obs.subscribe(onNext, onError, onComplete);
1
2
3
4
5
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx - Simple Observable
obs.subscribe(new Action1< Integer >() {
@Override
public void call(String value) { /* on emition */ }
}, new Action1< Throwable >() {
@Override
public void call(Throwable throwable) { /* on error */ }
}, new Action0() {
@Override
public void call() { /* on complete */ }
});
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx - Map Operator
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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();
}
});
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
1. Intro to Rx
- Observables are immutable
- Compose functions into processing chains
- Avoid callback hell
- Structured code, feels like the right way!
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 1: Intro to Rx
git clone git@github.com:3pillarlabs/rx_android_workshop.git
cd rx_android_workshop
git checkout mb1
git checkout -b mb1
- Explore the ExampleUnitTest class
- Rewrite the "testObservable" method using TestSubscriber
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
2. Lambda expression
"... they provide a clear and concise way to represent one method interface using an expression ... "
-- Java 8
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
2. Lambda expression
- There's no Java 8 support for Android ...
- ... but there's Retrolambda: backport of Java 8's lambda expressions to Java 7, 6, 5
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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; }
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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());
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 2: Less code with lambdas
git add -A && git commit -m "progress"
git checkout mb2
git checkout -b mb2
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
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 3: Explore Rx Operators
git add -A && git commit -m "progress"
git checkout mb3
git checkout -b mb3
- Please make all tests in ExploreSimpleOperatorsTest pass using only Rx operators!
- Fix the tests sequentially
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
4. Reactive HTTP with Retrofit
"Retrofit turns your HTTP API into a Java interface"
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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);
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 4: Reactive HTTP with Retrofit
git add -A && git commit -m "progress"
git checkout mb4
git checkout -b mb4
- Explore & execute tests for the provided API
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 5: Easy networking with reactive streams
git add -A && git commit -m "progress"
git checkout mb5
git checkout -b mb5
- Search movies by title using the api and display results in popup
- Don't forget to add INTERNET permission to the manifest
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
5. Handle Errors
- There's a runtime error in the current implementation. Please fix it!
- Remember to implement the onError method for your subscriber!
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
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: AndroidSchedulers.mainThread(), etc
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
6. 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 mb6
git checkout -b mb6
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
6. FlatMap
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
6. Multithread ?
RxTextView.textChanges(searchText)
.flatMap(title -> omdbApi.searchByTitle(title))
.subscribeOn(Schedulers.io());
RxTextView.textChanges(searchText)
.flatMap(title -> omdbApi.searchByTitle(title)
.subscribeOn(Schedulers.io()));
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 7: Unsubscribe
- Fix memory leaks
- Subscription.unsubscribe()
- CompositeSubscription
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 7: RxLifecycle
git add -A && git commit -m "progress"
git checkout mb7
git checkout -b mb7
- Allow for automatic completion of sequences based on Activity or Fragment lifecycle events - useful in Android, as incomplete subscriptions can cause memory leaks
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 8: Optimal "hot search"
git add -A && git commit -m "progress"
git checkout mb8
git checkout -b mb8
- MovieSerchService#last_title_should_match_search
should pass
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. Optimal "hot search"
To improve:
- avoid too many requests
- handle errors
- responses are not ordered
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. Limiting throughput
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. Handling errors
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. Handling errors
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. flatMap = merge(map)
- non blocking
- fail fast
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. flatMap multithread
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. concatMap
- Order is guaranteed
- Blocking!
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. concatMap
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. switchMap
- Subscribe for the last only
- Unsubscribe/cancel the previous
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
8. switchMap
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 9: Implement a RxBiding
git add -A && git commit -m "progress"
git checkout mb9
git checkout -b mb9
- Use RxListPopupWindow instead of listener
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
10. DB Integration
- SQLBrite - A lightweight wrapper around SQLiteOpenHelper and ContentResolver which introduces reactive stream semantics to queries.
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
10. DB Integration
...
@Inject
BriteDatabase db;
...
db.createQuery(table_name, query, params)
- Besides the sqlQuery & params, the method takes an additional parameter of table(s) on which to listen for changes
- Subscribe to the returned Observable which will immediately notify with a Query to run
- When you insert, update, or delete data, any subscribed queries will update with the new data instantly.
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
10. DB Integration
- You shall use MovieItemDao
- Let's have a quick look at the code
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 10: Populate view from DB
git add -A && git commit -m "progress"
git checkout mb10
git checkout -b mb10
- Show DB data in the recycler view
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 11: Save movie into DB
git add -A && git commit -m "progress"
git checkout mb11
git checkout -b mb11
- Request detailed movie
- Transform it into ContentValues (MovieItem)
- Save into DB using the DAO
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 12: Materilize
Wrap events and errors
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 12: Materilize
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 12: Backpressure
When Producer is faster than consumer
February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop
Exercise 12: Demo
git add -A && git commit -m "progress"
git checkout mb12
git checkout -b mb12
Mobos RxAndroid workshop
By Karoly Szanto
Mobos RxAndroid workshop
- 498