Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
REACTIVE
APPROACH
FOR SLOWPOKES
BY SERGEY TARASEVICH
WHERE IT STARTED…
• “раздуплить”
• “я бы тоже хотел думать мозгом”
• “я понимаю, шо я так сходу лиспом в
голову”
• “оно производит изменения...
Reactive
programming
REACTIVE IS …
• Functional
• Avoid intricate stateful programs, using clean input/output functions over
observable streams...
© Rob Wormald
ONE DOES NOT SIMPLY
BECOME REACTIVE
• New approach
• New thinking
• New data flow
• New error handling
• New language?
WHAT’S NEW?
RxJava
RXJAVA + JAVA 7
Удобно пи ец
Observable
.range(1, 4)
.delay(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(final...
RXJAVA + JAVA 8
Java 8 on Android
RXJAVA + JAVA 8λ + RETROLAMBDA
RXJAVA + KOTLIN
Observable
.range(1, 4)
.delay { integer ->
MathObservable
.sumInteger(Observable.range(1, integer))
.flatMap { targetSeco...
TERMINS
• Observable / Single
• lift(Operator)
• subscribeOn(Scheduler) / observeOn(Scheduler)
• subscribe(Observer)
• Obs...
OBSERVABLE
Single Multiple
Sync T getData() Iterable<T> getData()
Async Future<T> getData() Observable<T> getData()
OBSERVABLE
Single Multiple
Sync T getData() Iterable<T> getData()
Async Future<T> getData() Observable<T> getData()
© Ben ...
OBSERVABLE
Single Multiple
Sync T getData() Iterable<T> getData()
Async
Future<T> getData()
Single<T> getData()
Observable...
OBSERVABLE
Iterable Observable
T next() onNext(T)
throws Exception onError(Exception)
!hasNext() onComplete()
OBSERVABLE
observable
.map { … }
.subscribe(
{ data -> log(“onNext()”) },
{ error -> log(“onError()”) },
{ log(“onComplete...
OBSERVABLE
RXMARBLES.COM
• observable.first()
• observable.filter { x -> x > 10 }
• observable.delay(10, SECONDS)
• observable.mergeW...
OBSERVER
observable
.map { … }
.filter { … }
.subscribe(
{ data -> log(“onNext()”) },
{ error -> log(“onError()”) },
{ log...
OBSERVER
observable [“хочу сапоги”, “хочу шубу”, “хочу телефон”, …]
.map { … } [“сапоги” -> $200], [“шуба” -> $1000], …
.f...
OBSERVER
observable [“хочу парня нормального”]
.map { … } [#ERROR]
.filter { … } [#ERROR]
.subscribe(
{ data -> log(“onNex...
OBSERVER
observable [Ой, все!]
.map { … } [Ой, все!]
.filter { … } [Ой, все!]
.subscribe(
{ data -> log(“onNext()”) },
{ e...
SUBJECT
Subject = Observable + Observer
SUBJECT
observable
.map { … }
.filter { … }
.subscribe(
{ data -> log(“onNext()”) },
{ error -> log(“onError()”) },
{ log(...
SUBJECT
observable subject
.map { … }
.filter { … }
.subscribe(
{ data -> log(“onNext()”) },
{ error -> log(“onError()”) }...
SUBJECT
observable
.map { … }
.filter { … }
.subscribe(subject)
{ data -> log(“onNext()”) },
{ error -> log(“onError()”) }...
SUBJECT
• PublishSubject
• BehaviorSubject
• ReplaySubject
• AsyncSubject
SUBJECT
• PublishSubject - for Junior
• BehaviorSubject - for Middle
• ReplaySubject - for Senior
• AsyncSubject - for PM
SCHEDULERS
observable
.subscribeOn(…)
.observeOn(…)
.subscribe {
…
}
SCHEDULERS
observable
…
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
textView.setText(…)
} wow
so mainthreadish
Integration
RX
OR NOT RX
ARCHITECTURE
NETWORK LAYER
RestFacade
——————————————————————————————————————————————————
void getUser(Params params,
DataListener<User>...
MODEL LAYER
UserService(RestFacade)
——————————————————————————————————————————————————
void getProfile(UserProfileListener...
VIEW (IVIEW) LAYER
IUserView
——————————————————————————————————————————————————
void setName(String name)
void setOnSavePr...
PRESENTER LAYER
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
private UserPr...
PRESENTER LAYER
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
@Override
void...
LAYERS 1.0
L
L
L
C
C
C
L - listener
C - call
LAYERS 2.0
L - listener
C - call
O - observable
O
L
L
C(o)
C
C
LAYERS 3.0
L - listener
C - call
O - observable
O
O
LC
C(o)
C{}
LAYERS 4.0
L - listener
C - call
O - observable
O
O
O
C{}
C
C(o)
NOT SURE
IF RETROFIT IS ALREADY REACTIVE
NETWORK LAYER 1.0
RestFacade
——————————————————————————————————————————————————
void getUser(Params params,
DataListener<U...
NETWORK LAYER 2.0
RestFacade
——————————————————————————————————————————————————
void getUser(Params params,
DataListener<U...
MODEL LAYER 1.0
UserService(RestFacade)
——————————————————————————————————————————————————
void getProfile(UserProfileList...
MODEL LAYER 2.0
UserService(RestFacade)
——————————————————————————————————————————————————
void getProfile(UserProfileList...
VIEW (IVIEW) LAYER 1.0
IUserView
——————————————————————————————————————————————————
void setName(String name)
void setOnSa...
VIEW (IVIEW) LAYER 2.0
IUserView
——————————————————————————————————————————————————
void setName(String name)
void setOnSa...
PRESENTER LAYER 1.0
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
private Us...
PRESENTER LAYER 1.0
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
@Override
...
PRESENTER LAYER 2.0
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
void init(...
PRESENTER LAYER 2.0
UserProfilePresenter(UserService, IView)
——————————————————————————————————————————————————
void init(...
YOU SUBSCRIBE TO OBSERVABLE
BUT FIRE CALLBACK IN ONNEXT()
WTFs
BE ATTENTIVE
Observable<Void> saveProfile(UserProfile profile)
• userService.saveProfile(userProfile)
Do nothing!
• userSe...
BEHAVIOUR SUBJECT
Observable<Data> stream =
new BehaviorSubject(data)
…
stream.subscribe { data ->
… // first onNext() eve...
CONNECTABLE STREAM
ConnectableObservable statuses()
——————————————————————————————————————————————————
…
Subscription s = ...
CONNECTABLE STREAM
ConnectableObservable statuses()
——————————————————————————————————————————————————
…
Subscription s = ...
In the end
• Easy to understand?
• Easy to use?
• Huge error stacktraces?
• GC works hard?
• Low performance?
FAQ
• RxJava is cool (with Kotlin)
• You can become reactive step by step
• It makes you happier
SO…
LINKS
• http://reactivex.io/
• http://rxmarbles.com/
• https://github.com/ReactiveX/RxJava
• https://www.youtube.com/watch...
QUESTIONS?
THANKS!
Upcoming SlideShare
Loading in …5
×

GDG DevFest 2015 - Reactive approach for slowpokes

432 views

Published on

Probably everyone has heard about reactive programming but not everyone tried to use it in real projects.
This presentation is about reactive approach basics and about own experience of integrating this approach into real Android project step by step.

Published in: Software
  • Be the first to comment

GDG DevFest 2015 - Reactive approach for slowpokes

  1. 1. REACTIVE APPROACH FOR SLOWPOKES BY SERGEY TARASEVICH
  2. 2. WHERE IT STARTED…
  3. 3. • “раздуплить” • “я бы тоже хотел думать мозгом” • “я понимаю, шо я так сходу лиспом в голову” • “оно производит изменения в мозгу, которые делают программиста лучше” • “чик-чик и в продакшн” WHAT’S LEARNED
  4. 4. Reactive programming
  5. 5. REACTIVE IS … • Functional • Avoid intricate stateful programs, using clean input/output functions over observable streams. • Less is more • ReactiveX's operators often reduce what was once an elaborate challenge into a few lines of code. • Async error handling • Traditional try/catch is powerless for errors in asynchronous computations, but ReactiveX is equiped with proper mechanisms for handling errors. • Concurrency made easy • Observables and Schedulers in ReactiveX allow the programmer to abstract away low-level threading, synchronization, and concurrency issues.
  6. 6. © Rob Wormald
  7. 7. ONE DOES NOT SIMPLY BECOME REACTIVE
  8. 8. • New approach • New thinking • New data flow • New error handling • New language? WHAT’S NEW?
  9. 9. RxJava
  10. 10. RXJAVA + JAVA 7 Удобно пи ец
  11. 11. Observable .range(1, 4) .delay(new Func1<Integer, Observable<Integer>>() { @Override public Observable<Integer> call(final Integer integer) { return MathObservable .sumInteger(Observable.range(1, integer)) .flatMap(new Func1<Integer, Observable<Integer>>() { @Override public Observable<Integer> call(Integer targetSecondDelay) { return Observable .just(integer) .delay(targetSecondDelay, TimeUnit.SECONDS); } }); } }) .doOnSubscribe(new Action0() { @Override public void call() { _log(“…”); } }) .subscribe(new Observer<Integer>() { @Override public void onCompleted() { Timber.d("onCompleted"); IN JAVA
  12. 12. RXJAVA + JAVA 8 Java 8 on Android
  13. 13. RXJAVA + JAVA 8λ + RETROLAMBDA
  14. 14. RXJAVA + KOTLIN
  15. 15. Observable .range(1, 4) .delay { integer -> MathObservable .sumInteger(Observable.range(1, integer)) .flatMap { targetSecondDelay -> Observable .just(integer) .delay(targetSecondDelay, TimeUnit.SECONDS) } } .doOnSubscribe { Timber.d(“…”) } .subscribe( { integer -> Timber.d(“…”) }, { error -> Timber.d(error, "arrrr. Error") }, { Timber.d("onCompleted") } ) IN KOTLIN
  16. 16. TERMINS • Observable / Single • lift(Operator) • subscribeOn(Scheduler) / observeOn(Scheduler) • subscribe(Observer) • Observer • onNext() • onError() • onComplete() • Subject = Observable + Observer • Operators (map, flatMap, merge, delay, …) • Schedulers
  17. 17. OBSERVABLE Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData()
  18. 18. OBSERVABLE Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() © Ben Christensen (Netflix)
  19. 19. OBSERVABLE Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Single<T> getData() Observable<T> getData()
  20. 20. OBSERVABLE Iterable Observable T next() onNext(T) throws Exception onError(Exception) !hasNext() onComplete()
  21. 21. OBSERVABLE observable .map { … } .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } )
  22. 22. OBSERVABLE
  23. 23. RXMARBLES.COM • observable.first() • observable.filter { x -> x > 10 } • observable.delay(10, SECONDS) • observable.mergeWith(observable2) • observable.debounce(1, SECONDS) • observable.skipUntil(observable2)
  24. 24. OBSERVER observable .map { … } .filter { … } .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } ) }Observer
  25. 25. OBSERVER observable [“хочу сапоги”, “хочу шубу”, “хочу телефон”, …] .map { … } [“сапоги” -> $200], [“шуба” -> $1000], … .filter { … } [ ценник < $500 ] .subscribe( { data -> log(“onNext()”) }, Окей, записал { error -> log(“onError()”) }, { log(“onComplete”) } )
  26. 26. OBSERVER observable [“хочу парня нормального”] .map { … } [#ERROR] .filter { … } [#ERROR] .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, o_O { log(“onComplete”) } )
  27. 27. OBSERVER observable [Ой, все!] .map { … } [Ой, все!] .filter { … } [Ой, все!] .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } Ой, все! )
  28. 28. SUBJECT Subject = Observable + Observer
  29. 29. SUBJECT observable .map { … } .filter { … } .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } )
  30. 30. SUBJECT observable subject .map { … } .filter { … } .subscribe( { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } )
  31. 31. SUBJECT observable .map { … } .filter { … } .subscribe(subject) { data -> log(“onNext()”) }, { error -> log(“onError()”) }, { log(“onComplete”) } )
  32. 32. SUBJECT • PublishSubject • BehaviorSubject • ReplaySubject • AsyncSubject
  33. 33. SUBJECT • PublishSubject - for Junior • BehaviorSubject - for Middle • ReplaySubject - for Senior • AsyncSubject - for PM
  34. 34. SCHEDULERS observable .subscribeOn(…) .observeOn(…) .subscribe { … }
  35. 35. SCHEDULERS observable … .observeOn(AndroidSchedulers.mainThread()) .subscribe { textView.setText(…) } wow so mainthreadish
  36. 36. Integration
  37. 37. RX OR NOT RX
  38. 38. ARCHITECTURE
  39. 39. NETWORK LAYER RestFacade —————————————————————————————————————————————————— void getUser(Params params, DataListener<User> listener) void pullUserNotifications(Params params, DataListener<Notification> listener) void saveProfile(UserProfile profile)
  40. 40. MODEL LAYER UserService(RestFacade) —————————————————————————————————————————————————— void getProfile(UserProfileListener listener) { … } void addUserNotificationListener( NotificationListener listener) { … } void startListenNotifications() { … } void stopListenNotifications() { … }
  41. 41. VIEW (IVIEW) LAYER IUserView —————————————————————————————————————————————————— void setName(String name) void setOnSaveProfileListener(Listener listener) —————————————————————————————————————————————————— INotificationsView —————————————————————————————————————————————————— void setNotifications(List<Notification> notifications) void setOnNotificationClickListener( Listener<Notification> listener) ——————————————————————————————————————————————————
  42. 42. PRESENTER LAYER UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— private UserProfile profile; private List<Notification> notifications; void init() { userService.addUserNotificationListener(this) view.setOnSaveProfileListener(this) userService.getUserProfile(this) userService.startListenNotifications() }
  43. 43. PRESENTER LAYER UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— @Override void onUserProfileReceived(UserProfile profile) { this.profile = profile view.setName(profile.name + “ “ profile.lastName) } @Override void onNotificationReceived(Notification notif) { this.notifications.add(notif) view.setNotifications(this.notifications) } @Override void onSaveProfile() { userService.saveProfile(…) }
  44. 44. LAYERS 1.0 L L L C C C L - listener C - call
  45. 45. LAYERS 2.0 L - listener C - call O - observable O L L C(o) C C
  46. 46. LAYERS 3.0 L - listener C - call O - observable O O LC C(o) C{}
  47. 47. LAYERS 4.0 L - listener C - call O - observable O O O C{} C C(o)
  48. 48. NOT SURE IF RETROFIT IS ALREADY REACTIVE
  49. 49. NETWORK LAYER 1.0 RestFacade —————————————————————————————————————————————————— void getUser(Params params, DataListener<User> listener) void pullUserNotifications(Params params, DataListener<Notification> listener) void saveProfile(UserProfile profile)
  50. 50. NETWORK LAYER 2.0 RestFacade —————————————————————————————————————————————————— void getUser(Params params, DataListener<User> listener) Observable<User> getUser(Params params) void pullUserNotifications(Params params, DataListener<Notification> listener) Observable<Notification> pullUserNotifications( Params params) void saveProfile(UserProfile profile) Observable<Void> saveProfile(UserProfile profile)
  51. 51. MODEL LAYER 1.0 UserService(RestFacade) —————————————————————————————————————————————————— void getProfile(UserProfileListener listener) { … } void addUserNotificationListener( NotificationListener listener) { … } void startListenNotifications() { … } void stopListenNotifications() { … }
  52. 52. MODEL LAYER 2.0 UserService(RestFacade) —————————————————————————————————————————————————— void getProfile(UserProfileListener listener) { … } Observable<UserProfile> getProfile() { … } void addUserNotificationListener( NotificationListener listener) { … } void startListenNotifications() { … } void stopListenNotifications() { … } Observable<Notification> getNotifications() { … }
  53. 53. VIEW (IVIEW) LAYER 1.0 IUserView —————————————————————————————————————————————————— void setName(String name) void setOnSaveProfileListener(Listener listener) —————————————————————————————————————————————————— INotificationsView —————————————————————————————————————————————————— void setNotifications(List<Notification> notifications) void setOnNotificationClickListener( Listener<Notification> listener) ——————————————————————————————————————————————————
  54. 54. VIEW (IVIEW) LAYER 2.0 IUserView —————————————————————————————————————————————————— void setName(String name) void setOnSaveProfileListener(Listener listener) Observable<Void> saveProfileClicks() —————————————————————————————————————————————————— INotificationsView —————————————————————————————————————————————————— void setNotifications(List<Notification> notifications) void setOnNotificationClickListener( Listener<Notification> listener) Observable<Notification> notificationClicks() ——————————————————————————————————————————————————
  55. 55. PRESENTER LAYER 1.0 UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— private UserProfile profile; private List<Notification> notifications; void init() { userService.addUserNotificationListener(this) view.setOnSaveProfileListener(this) userService.getUserProfile(this) userService.startListenNotifications() }
  56. 56. PRESENTER LAYER 1.0 UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— @Override void onUserProfileReceived(UserProfile profile) { this.profile = profile view.setName(profile.name + “ “ + profile.lastName) } @Override void onNotificationReceived(Notification notif) { this.notifications.add(notif) view.setNotifications(this.notifications) } @Override void onSaveProfile() { userService.saveProfile(…) }
  57. 57. PRESENTER LAYER 2.0 UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— void init() { userService.getUserProfile() .map { profile -> formatName(profile) } .observeOn(AndroidSchedulers.mainThread()) .subscribe { name -> view.setName(name) } userService.pullNotifications() .observeOn(AndroidSchedulers.mainThread()) .subscribe { notifications -> view.setNotifications(notifications) } … }
  58. 58. PRESENTER LAYER 2.0 UserProfilePresenter(UserService, IView) —————————————————————————————————————————————————— void init() { … view.saveProfileClicks() .withLatestFrom(currentProfileStream, …) .flatMap { profile -> userService.saveProfile(profile) } .subscribe( { success -> …}, { error -> … } { … } ) }
  59. 59. YOU SUBSCRIBE TO OBSERVABLE BUT FIRE CALLBACK IN ONNEXT()
  60. 60. WTFs
  61. 61. BE ATTENTIVE Observable<Void> saveProfile(UserProfile profile) • userService.saveProfile(userProfile) Do nothing! • userService.saveProfile(userProfile).subscribe() Do the thing!
  62. 62. BEHAVIOUR SUBJECT Observable<Data> stream = new BehaviorSubject(data) … stream.subscribe { data -> … // first onNext() event is on the same thread }
  63. 63. CONNECTABLE STREAM ConnectableObservable statuses() —————————————————————————————————————————————————— … Subscription s = statuses().connect() … statuses().subscribe(…) statuses().subscribe(…) statuses().subscribe(…) … s.unsibscribe() statuses().connect() …
  64. 64. CONNECTABLE STREAM ConnectableObservable statuses() —————————————————————————————————————————————————— … Subscription s = statuses().connect() … statuses().subscribe(…) // Where is my data? statuses().subscribe(…) // Where is my data? statuses().subscribe(…) // Where is my data? … s.unsibscribe() statuses().connect() …
  65. 65. In the end
  66. 66. • Easy to understand? • Easy to use? • Huge error stacktraces? • GC works hard? • Low performance? FAQ
  67. 67. • RxJava is cool (with Kotlin) • You can become reactive step by step • It makes you happier SO…
  68. 68. LINKS • http://reactivex.io/ • http://rxmarbles.com/ • https://github.com/ReactiveX/RxJava • https://www.youtube.com/watch? v=SyWFvn0I6m8 • https://speakerdeck.com/benjchristensen/ functional-reactive-programming-in-the-netflix- api-lambdajam-2013
  69. 69. QUESTIONS?
  70. 70. THANKS!

×