
Android Application Architecture with RxJava
by Predko Silvestr
GDG Ternopil
Content
-
Reactive programming
-
Why I need Rx?
-
RxJava and RxAndroid
-
RxLifecycle
-
Retrofit 2.0, Realm
-
Design app architecture
What about streams?

Reactive Programming
Reactive programming built on strems

For Example:
b = 4;
c = 6;
a = b + c; // a = 10
b = 10; // a = 16
c = 7; // a = 17Imperative
Reactive
b = 4;
c = 6;
a = b + c; // a = 10
b = 10; // a = 10
c = 7; // a = 10vs
Why I need Rx?
-
For executing code in background
-
For code simplicity
-
For error handling
-
For scalable app architecture

Android Async Tools
RxJava and RxAndroid
RxJava is a combination of the best ideas from
the Observer and Iterator pattern
The Basics
The basic building blocks of reactive code are Observables and Subscribers
An Observable emits items; a Subscriber consumes those items.
Hello World!
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello world!");
sub.onCompleted();
}
}
);
myObservable.subscribe(mySubscriber);Subscriber<String> mySubscriber = new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
};it's the same as sub.onComplete, but also throw exception.
sub.onError(Throwable e)Text
Creating Observables
Observable.create(onSubscribe);
// accept OnSubscribe object
// the most complex creation of Observable
Observable.empty(); //emits nothing and then completes
Observable.never(); //that emits nothing at all
Observable.error(new Throwable("error")); //emits nothing and then signals an error


Empty, Never, Error
Just
Observable.just("Hello", "World", "!").subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("Completed");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
System.out.println("Next: " + s);
}
});Output
Next: Hello
Next: World
Next: !
CompletedInterval
Observable.interval(500, TimeUnit.MILLISECONDS)
.toBlocking()
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
System.out.println("Iteration");
}
});
create an Observable that emits a sequence of integers spaced by a particular time interval
From
List<String> arr = Arrays.asList("Hello", "World");
// create Observable from:
Observable.from(arr); // from Iterable
Observable.from(new String[]{"Hello", "World"}); // from Array
Observable.fromCallable(() -> "Hello"); // from Callableconvert some other object or data structure into an Observable
Text
Subscribing
with Subscriber
with Action1
.subscribe(new Subscriber<Forecast>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Forecast forecast) {
}
});.subscribe(new Action1<Forecast>() {
@Override
public void call(Forecast forecast) {
}
});.subscribe(new Action1<Forecast>() {
@Override
public void call(Forecast forecast) {
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
}
});Real Example with Operators
public static Observable<String> getObservable(String[] arr) {
return Observable.create((Observable.OnSubscribe<String>) subscriber -> {
for (String s : arr) {
subscriber.onNext(s);
}
subscriber.onCompleted();
});
}create observable
Hello
GDG
Ternopil
!output
Transformation
-
map
{Hello}
{GDG}
{Ternopil}
{!}output
getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return "{" + s + "}";
}
})
.subscribe(System.out::println);what you get
emit type
-
flatmap
getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.flatMap(new Func1<String, Observable<Integer>>() {
@Override
public Observable<Integer> call(String s) {
return Observable.just(s.hashCode());
}
})
.subscribe(System.out::println);-
scan
getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.scan(new Func2<String, String, String>() {
@Override
public String call(String s, String s2) {
return s + " " + s2;
}
}).subscribe(System.out::println);Hello
HelloGDG
HelloGDGTernopil
HelloGDGTernopil!
output
Filtering
getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.filter((s) -> !s.startsWith("H"))
.subscribe(System.out::println);output
examples
GDG
Ternopil
!getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.filter((s) -> !s.startsWith("H"))
.take(2)
.subscribe(System.out::println);GDG
Ternopil
getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
.filter((s) -> !s.startsWith("H"))
.take(2)
.last()
.subscribe(System.out::println);Ternopil
Combining
public static Observable<String> getObservable2(String name) {
return Observable.create((Observable.OnSubscribe<String>) subscriber -> {
subscriber.onNext(name);
subscriber.onCompleted();
});
}getObservable(new String[]{"Hello", "GDG", "Ternopil", "!"})
// save executing sequence
.concatWith(getObservable2("Observable2"))
// gets the first emitted element
.mergeWith(getObservable2("Observable2"))
.subscribe(System.out::println);Hello
GDG
Ternopil
!
Observable2output
How to execute it in Background?
Observable.create(subscriber -> {
for (int i = 0; i < 500; i++) {
try {
Thread.sleep(500);
subscriber.onNext("Hello");
} catch (InterruptedException e) {
subscriber.onError(e);
}
}
subscriber.onCompleted();
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())Execute on
Get Result on
.subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.computation())
.subscribeOn(Schedulers.from(Executor))Problems
Observable.create(subscriber -> {
...
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())Memory Leaks

RxLifecycle
Written by

Installation
compile 'com.trello:rxlifecycle:0.4.0'
// If you want pre-written Activities and Fragments you can subclass as providers
compile 'com.trello:rxlifecycle-components:0.4.0'Usage
1.
2.
MainActivity extends RxAppCompatActivity.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(bindToLifecycle())or
Create PublishSubject
public class MainActivity extends Activity {
PublishSubject<ActivityEvent> subject = PublishSubject.create();
}
Override lifecycle methods
@Override
protected void onDestroy() {
super.onDestroy();
subject.onNext(ActivityEvent.DESTROY);
}
@Override
protected void onStop() {
super.onStop();
subject.onNext(ActivityEvent.STOP);
}set up in compose()
.compose(RxLifecycle.bindActivity(subject));Retrofit 2.0 and Realm
RxJava is Everywhere
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);Retrofit Example:
Realm Example:
Realm realm = Realm.getDefaultInstance();
RealmResults<Person> persons = realm.where(Person.class).findAll();
Person person = persons.first();
Observable<Realm> realmObservable = realm.asObservable();
Observable<RealmResults<Person>> resultsObservable = persons.asObservable();
Observable<Person> objectObservable = person.asObservable();Design app architecture with RxJava
Implement Repository Pattern
Cache Observables
Turn on your imagination
Repository Pattern

Observable Caching
Observable observable = Observable.create(subscriber -> {
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(bindToLifecycle())
.cache();You need save instance of observable
- Loader
- Singleton
- Fragment
with:
With Loader
public class ObservableLoader extends Loader<List<Observable>>private SparseArray<Observable> observableSparseArray;private Map<String, Observable> observableMap;or
public void addObservable(Observable<Integer> observable, String id)@Override
protected void onStartLoading() {
super.onStartLoading();
deliverResult(getObservableList());
}1.
Implement own loader realization
With Loader
2.
In Activity or Fragment
Init Loader and check the presence of observable by id
Get instance of Loader
getLoaderManager().getLoader(1);Add Observable to map in Loader
Rx World
RxPermission
RxNetty
RxStore
RxLoader
RxPalette
RxBlur
or
Write your own library
Questions & Answers
contact me:
Facebook - silvestr.predko
Twitter - @Silvestr1994
Google+ - SilvestrPredko
Android Application Architecture with RxJava
By Silvestr Predko
Android Application Architecture with RxJava
- 1,519