Alejandro Vidal Rodriguez
Director of Engineer @TribalScale
www.tribalscale.ae
we are hiring!
Set up our Rx project
Types of Observables
Streams
Operators
Threading
Exceptions
Handling real time updates (DEMO)
Warnings!
an app with real time updates!
Repository
git clone git@github.com:goofyahead/RxWorkshop.git
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.tsl057.rxjavaplaygroundjava"
minSdkVersion 24
...
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.google.firebase:firebase-firestore:12.0.1'
...
implementation "io.reactivex.rxjava2:rxandroid:$RX_ANDROID_VERSION"
implementation "io.reactivex.rxjava2:rxjava:$RX_JAVA_VERSION"
}
int result = 0;
int a = 3;
int b = 2;
result = a + b; //result = 5
a++;"In computing, reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. "
Observable
Observer
Observable<Integer> myObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
});Observable<Integer> myObservable = Observable.just(2, 3, 4);
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
// we are subscribed, we get a reference to dispose our subscription
}
@Override
public void onNext(Integer integer) {
// a new value was emitted
}
@Override
public void onError(Throwable e) {
// something bad happened
}
@Override
public void onComplete() {
// stream is finished
}
};
observable.subscribe(observer); <= Only now things start to happen.Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
}; SingleObserver<Integer> obs = new SingleObserver<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
};CompletableObserver obs = new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
};MaybeObserver<Integer> maybeObserver = new MaybeObserver<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};Flowable<String> flowable = new Flowable<String>() {
@Override
protected void subscribeActual(Subscriber<? super String> s) {
s.onNext("hello");
}
};
flowable
.buffer(12)
.onBackpressureDrop()
.subscribe(); return Observable.create(emitter -> collection.addSnapshotListener((queryDocumentSnapshots, e) -> {
for (DocumentChange document : queryDocumentSnapshots.getDocumentChanges()) {
if (!emitter.isDisposed()) {
Log.d(TAG, document.getDocument().getData().toString());
emitter.onNext(document.getDocument().toObject(Product.class));
}
}
}));//Java stream
Optional<Product> found = productList
.stream()
.filter(product -> (product.id.equalsIgnoreCase(modifiedProduct.id)))
.findAny();//Rx Stream
Maybe<Product> productMaybe = Observable.fromIterable(productList)
.filter(product -> (product.id.equalsIgnoreCase(modifiedProduct.id)))
.firstElement();Observable
.fromIterable(productList)
.flatMap(product -> Observable.just(1,3,4,6))
.firstElement();flatMap
Observable
.fromIterable(productList)
.map(product -> product.name)
.firstElement();map
Observable
.fromIterable(productList)
.flatMap(product -> Observable.just(1,3,4,6))
.filter(number -> number > 3)
.firstElement();filter
Observable.fromIterable(productList)
.map(product -> product.name)
.distinct();distinct
Single<List<String>> unique = Observable.fromIterable(productList)
.map(product -> product.name)
.debounce(300, TimeUnit.MILLISECONDS)
.toList();debounce
Observable.fromIterable(productList)
.map(product -> product.name)
.groupBy(s -> {
switch (s.charAt(0)){
case 'a':
case 'c':
return "starters";
case 'r':
case 'w':
return "weird";
default:
return "unknown";
}
});groupBy
Observable.fromCallable(slowCallToBackend())
.map(product -> product.name)
.timeout(3000, TimeUnit.MILLISECONDS);timeout
Observable.fromIterable(productList)
.map(product -> product.name)
.delay(3, TimeUnit.SECONDS)
.replay(10);replay
http://reactivex.io/documentation/operators usersObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { println(it) }val usersObservable = Observable.fromCallable {
usersDao.loadAll()
}Schedulers.computation().
Contains several threads for computations.
The number of threads depends on the number of the processes available for Java on this device.Schedulers.io().
Perfect for the I/O activities, like reading or recording into a database, server requests.Schedulers.newThread().
This thread will create a new thread whenever someone subscribes.
After the work is done, the thread will be finished.Schedulers.trampoline().
Enables you to delay the task in the current thread and queue it.
This scheduler will process its queue and start tasks one by one. Single<Integer> singleA = Single.fromCallable( slowFunctionA() )
.timeout(300, TimeUnit.MILLISECONDS)
.retry(5);
Single<Integer> singleB = Single.fromCallable( slowFunctionB() )
.timeout(600, TimeUnit.MILLISECONDS)
.retry(5);
Single.zip(singleA, singleB, (a, b) -> a + b )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();repository.getProductObservable()
.filter(product -> product.price < 5)
.subscribe(
product -> listener.onProductOffer(product),
throwable -> Observable.just(new Product())
);repository.getProductObservable()
.filter(product -> product.price < 5)
.subscribe(new Observer<Product>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(Product product) {}
@Override
public void onError(Throwable e) {}
@Override
public void onComplete() {}
});public Observable<Product> getProductObservable() {
return Observable.create(emitter -> collection.addSnapshotListener(
(queryDocumentSnapshots, e) -> {
for (DocumentChange document : queryDocumentSnapshots.getDocumentChanges()) {
if (!emitter.isDisposed()) {
Log.d(TAG, document.getDocument().getData().toString());
emitter.onNext(document.getDocument().toObject(Product.class));
}
}
}
));
} public void subscribeAllProducts(ProductListener.ModifiedProduct listener) {
repository
.getProductObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(product -> listener.onProductModified(product));
}
public void subscribeOffers(ProductListener.OfferProduct listener) {
repository.getProductObservable()
.filter(product -> product.price < 5)
.subscribe(product -> listener.onProductOffer(product),
throwable -> Observable.just(new Product()));
}public void productChanged(Product modifiedProduct) {
Optional<Product> found = productList
.stream()
.filter(product -> (product.id.equalsIgnoreCase(modifiedProduct.id)))
.findAny();
if (!found.isPresent()) {
productList.add(modifiedProduct);
notifyItemInserted(productList.size());
} else {
OptionalInt position = IntStream.range(0, productList.size())
.filter(i -> (productList.get(i).id.equalsIgnoreCase(modifiedProduct.id)))
.findFirst();
found.get().updateWith(modifiedProduct);
notifyItemChanged(position.getAsInt());
}
}.subscribe(new Observer<Product>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
}RxJava 2 changes:
https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0
RxJava article
https://android.jlelse.eu/reactive-programming-for-android-d55bdbb438b4
DataBinding & lifecycle
https://android.jlelse.eu/android-architecture-components-livedata-with-data-binding-7bf85871bbd8
MVVM & Rx
https://proandroiddev.com/mvvm-architecture-using-livedata-rxjava-and-new-dagger-android-injection-639837b1eb6c
Official doc
http://reactivex.io/
Java Streams
http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.htmlcontact
arodriguez@tribalscale.com
https://medium.com/@goofyahead