45
Reactive Programming RxJava + Android

2 презентация rx java+android

Embed Size (px)

Citation preview

Page 1: 2 презентация rx java+android

Reactive Programming RxJava + Android

Page 2: 2 презентация rx java+android
Page 3: 2 презентация rx java+android

Streams (data flow)

Page 4: 2 презентация rx java+android

Reactive eXtensions ?

Page 5: 2 презентация rx java+android

Rx Observer pattern• Observable • Observer/Subscriber• Subscription• Subject

Page 6: 2 презентация rx java+android

onNext, onCompleted, and onErrornew Observer<T>() { @Override public void onNext(T element) { // called when Observable «pushes» new event. }

@Override public void onCompleted() { // when stream is successfully completed(terminal state) }

@Override public void onError(Throwable e) { // bad news, stream is ends with exception (terminal state) }};

Page 7: 2 презентация rx java+android

Rx Basics

http://reactivex.io/

Page 8: 2 презентация rx java+android

- Emit 0 or N elements- Fails with exception -> onError()- Normally completes -> onCompleted()

Observable – Observer Contract

Page 9: 2 презентация rx java+android

Stream creationpublic static Observable<String> helloWorldStream() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { if (!subscriber.isUnsubscribed()) { try { subscriber.onNext("Hello"); subscriber.onNext("World"); subscriber.onCompleted(); } catch (Exception ex) { subscriber.onError(ex); } } } });}

Page 10: 2 презентация rx java+android

Stream creationpublic static Observable<String> helloWorldStream() { return Observable.create(subscriber -> { if (!subscriber.isUnsubscribed()) { try { subscriber.onNext("Hello"); subscriber.onNext("World"); subscriber.onCompleted(); } catch (Exception ex) { subscriber.onError(ex); } } });}

Page 11: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream.subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

Page 12: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream.subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

Page 13: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream.subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

Page 14: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream.subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

Page 15: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream.subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

"D:\JVM\Java JDK\bin\java"

Hello World

Process finished with exit code 0

Page 16: 2 презентация rx java+android

Hello World@Test public void helloWorldTest() { Observable<String> stream = helloWorldStream(); stream .reduce((prev, newOne) -> prev + " " + newOne ) .subscribe(result -> { System.out.println(result); }, err -> { err.printStackTrace(); });}

"D:\JVM\Java JDK\bin\java"

Hello World

Process finished with exit code 0

Page 17: 2 презентация rx java+android

OperatorsCreating – create, defer, from, interval, timer, start . . .Transforming – flatMap, map, scan, groupBy, buffer . . .Filtering – filter, debounce, distinct, take , first, egnoreElements . . .Combining – combineLatest, merge, startWith, switch, zip . . .Conditional & Boolean – contains, skipWhile, takeWhile, takeUntil, all . . .Math & Agregation – reduce, sum, min, max, count . . . And others . . .

http://reactivex.io/documentation/operators.html

Page 18: 2 презентация rx java+android

Creating operatorsObservable.just(1, 2, 3, 4);

Observable.from(Arrays.asList(“zero", "one", "two", "three"));

Observable.interval(200, TimeUnit.MILLISECONDS);

Observable.error(new Exception(" :`( "));

Page 19: 2 презентация rx java+android

Transforming operatorsObservable.just(2, 4, 6, 8, 10, 25, 43) .map(num -> new Pair<Integer, Double>(num, Math.sqrt(num))) .subscribe(pair -> println("new element is -> " + pair));

Observable.just(2, 4, 6, 8, 10, 25, 43) .scan((x, y ) -> x + y) .subscribe(sum -> println("Sum is: (" + sum + ")"));

Page 20: 2 презентация rx java+android

Filtering operatorsObservable.just(2, 30, 22, 5, 60, 1) .filter(num -> num > 10) .subscribe(num -> println("Filtered -> " + num));

Page 21: 2 презентация rx java+android

Combining operatorsObservable<Integer> ones = Observable.just(1, 1, 1);Observable<Integer> twos = Observable.just(2, 2);Observable .concat(ones, twos) .subscribe(res -> System.out.println(res));

Page 22: 2 презентация rx java+android

Combining operatorsObservable<Integer> ones = Observable.just(1, 1, 1);Observable<Integer> twos = Observable.just(2, 2);Observable .combineLatest(ones, twos, (o, t) -> "1 stream ->" + o + "\n 2 stream -> " + t) .subscribe(res -> System.out.println(res));

Page 23: 2 презентация rx java+android

Conditional & Boolean operators

Observable<Integer> zeros = Observable.just(0, 0, 0).delay(200, MILLISECONDS);Observable<Integer> nums = Observable.just(1, 2, 3).delay(100, MILLISECONDS);Observable<Integer> dozens = Observable.just(10, 20, 60).delay(300, MILLISECONDS);

Observable.amb(zeros, nums, dozens) .subscribe(res -> System.out.println(res)); // prints 1 2 3

Page 24: 2 презентация rx java+android
Page 25: 2 презентация rx java+android

RxBuspublic class RxBus { private RxBus() { throw new RuntimeException("Not allowed to create instance ");}; private static final Subject<Object, Object> bus = new SerializedSubject<>(PublishSubject.create());

public static void send(Object o) { bus.onNext(o); }

public static Observable<Object> toObserverable() { return bus.asObservable(); }

public static boolean hasObservers() { return bus.hasObservers(); }

public static <T>Observable<T> observeEvent(Class<T> clazz) { return bus.ofType(clazz).asObservable(); }}

Page 26: 2 презентация rx java+android

RxBuspublic class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RxBus.send(new ActivityCreatedEvent()); // . . . more logic here

}}

Page 27: 2 презентация rx java+android

RxBuspublic class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RxBus.send(new ActivityCreatedEvent()); // . . . more logic here}

class SuperBusyService extends Service { private final CompositeSubscription compSub = new CompositeSubscription(); @Override public void onCreate() { super.onCreate(); compSub.add(RxBus.observEvent(ActivityCreatedEvent.class) .subscribe(event -> doSomeLongOperation(), err -> handleErr(err))); }

@Override public void onDestroy() { super.onDestroy(); compSub.clear(); } . . .

Page 28: 2 презентация rx java+android

Simple Timer

Page 29: 2 презентация rx java+android

Simple Timerpublic void launchTicker() { final Long secondsDisabled = 60L; // user not allowed to send request for new sms tickerSub = Observable.interval(1, TimeUnit.SECONDS) .takeUntil(it -> it >= secondsDisabled -1 /* starts from 0 */ ) .map (sec -> (secondsDisabled - sec)) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe (() -> llSendAgain.isEnabled = false ) .doOnCompleted (() -> llSendAgain.isEnabled = true) .subscribe(time -> tvTicker.setText(getString(R.string.sms_send_again_timer, time)) , err -> handleError(err));

}

Page 30: 2 презентация rx java+android

«Do» operators in actionpublic class HomeScreenPresenter { final HomeView view; final HomeInteractor interactor = new HomeInteractorImpl();

public HomeScreenPresenter(HomeView view){ this.view = view; }

public void getClientData(String token) { view.showProgress(); view.manageSubscription(interactor.loadClientData(token) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(result -> { view.hideProgress(); view.onDataReady(result); }, err -> { view.hideProgress(); view.handleError(err); }) ); }}

Page 31: 2 презентация rx java+android

«Do» operators in actionpublic class HomeScreenPresenter { final HomeView view; final HomeInteractor interactor = new HomeInteractorImpl();

public HomeScreenPresenter(HomeView view){ this.view = view; }

public void getClientData(String token) { view.showProgress(); view.manageSubscription(interactor.loadClientData(token) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(result -> { view.hideProgress(); view.onDataReady(result); }, err -> { view.hideProgress(); view.handleError(err); }) ); }}

Page 32: 2 презентация rx java+android

«Do» operators in actionpublic class HomeScreenPresenter { final HomeView view; final HomeInteractor interactor = new HomeInteractorImpl();

public HomeScreenPresenter(HomeView view){ this.view = view; }

public void getClientData(String token) { view.manageSubscription(interactor.loadClientData(token) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .doOnSubscribe(view::showProgress) .doOnTerminate(view::hideProgress) .subscribe(result -> { view.onDataReady(result); }, err -> { view.handleError(err);}) ); }}

Page 33: 2 презентация rx java+android

«Do» operators in actionpublic class HomeScreenPresenter { final HomeView view; final HomeInteractor interactor = new HomeInteractorImpl();

public HomeScreenPresenter(HomeView view){ this.view = view; }

public void getClientData(String token) { view.manageSubscription(interactor.loadClientData(token) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .compose(RxUtils.progressBarVisibility(view)) .subscribe(result -> { view.onDataReady(result); }, err -> { view.handleError(err);}) ); }}

Page 34: 2 презентация rx java+android

«Do» operators in actionpublic class HomeScreenPresenter { final HomeView view; final HomeInteractor interactor = new HomeInteractorImpl();

public HomeScreenPresenter(HomeView view){ this.view = view; }

public void getClientData(String token) { view.manageSubscription(interactor.loadClientData(token) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .compose(RxUtils.progressBarVisibility(view)) .subscribe(result -> { view.onDataReady(result); }, err -> { view.handleError(err);}) ); }}

public static <T> Observable.Transformer<T, T> progressBarVisibility(HomeView view) { return targetObservable -> targetObservable.doOnSubscribe(view::showProgress) .doOnTerminate(view::hideProgress);}

Page 35: 2 презентация rx java+android

Validationfinal Observable<Boolean> nameObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> emailObservable = RxTextView.textChanges(edtEmail) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> passwordObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Subscription combinedSub = Observable

.combineLatest(nameObservable, emailObservable, passwordObservable, (name, mail, pass) -> name && mail && pass) .distinctUntilChanged() .subscribe(btnProceed::setEnabled);

compositeSubscription.add(combinedSub);

Page 36: 2 презентация rx java+android

Validationfinal Observable<Boolean> nameObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> emailObservable = RxTextView.textChanges(edtEmail) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> passwordObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Subscription combinedSub = Observable

.combineLatest(nameObservable, emailObservable, passwordObservable, (name, mail, pass) -> name && mail && pass) .distinctUntilChanged() .subscribe(btnProceed::setEnabled);

compositeSubscription.add(combinedSub);

Page 37: 2 презентация rx java+android

Validationfinal Observable<Boolean> nameObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> emailObservable = RxTextView.textChanges(edtEmail) .skip(1) .map(text -> /* validateInput with side effect */);

final Observable<Boolean> passwordObservable = RxTextView.textChanges(edtPassword) .skip(1) .map(text -> /* validateInput with side effect */);

final Subscription combinedSub = Observable

.combineLatest(nameObservable, emailObservable, passwordObservable, (name, mail, pass) -> name && mail && pass) .distinctUntilChanged() .subscribe(btnProceed::setEnabled);

compositeSubscription.add(combinedSub);

Page 38: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .flatMap(ApiService::searchItems) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 39: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .debounce(205, TimeUnit.MILLISECONDS) .flatMap(ApiService::searchItems) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 40: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .debounce(205, TimeUnit.MILLISECONDS) .switchMap(ApiService::searchItems) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 41: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .debounce(205, TimeUnit.MILLISECONDS) .switchMap(ApiService::searchItems) .onErrorResumeNext(err -> Observable.empty()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 42: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .debounce(205, TimeUnit.MILLISECONDS) .switchMap(ApiService::searchItems) .retryWhen(new NetworkConnectivity()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 43: 2 презентация rx java+android

«Live» searchRxTextView.textChanges(searchEditText) .debounce(205, TimeUnit.MILLISECONDS) .switchMap(ApiService::searchItems) .retryWhen(new NetworkConnectivityIncremental(context, 5, 15, SECONDS)) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::updateList, t-> showError());

https://lorentzos.com/improving-ux-with-rxjava-4440a13b157f#.19yawyfss

Page 44: 2 презентация rx java+android

Easy concurrencyNetApiService.loadDocument(docId) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) // want find matches or smth ASAP .map(data -> MatchFinder.find(data, PATTERN)) // work done, can swith on low priority 'IO' pool .observeOn(Schedulers.io()) .doOnNext(processedData -> DataProvider.saveProcessedDocument(docId, processedData)) .observeOn(AndroidSchedulers.mainThread()) .subscribe(/* do something with result */);

Page 45: 2 презентация rx java+android

https://twitter.com/mr_art_Core