The Art of Rx10. • î ÷åì äóìàòü?
9
Умение думать. Практика
11. • î ÷åì äóìàòü?
• êàê äóìàòü?
9
Умение думать. Практика
20. • êàê ïîëüçîâàòåëü
• êàê äèçàéíåð
• êàê ïðåäëàãàåò ôóíäàìåíòàëüíûé ôðåéìâîðê
11
Как думать мобильному разработчику?
23. • äåëàåò ðàçðàáîòêó ïðîùå/ëó÷øå/áûñòðåå
• ïðèâíîñèò ÷òî-òî êîíöåïòóàëüíî íîâîå
12
Фундаментальный фреймворк
24. • äåëàåò ðàçðàáîòêó ïðîùå/ëó÷øå/áûñòðåå
• ïðèâíîñèò ÷òî-òî êîíöåïòóàëüíî íîâîå
• ïðîðàñòàåò âî âñå ïîäñèñòåìû
12
Фундаментальный фреймворк
25. • äåëàåò ðàçðàáîòêó ïðîùå/ëó÷øå/áûñòðåå
• ïðèâíîñèò ÷òî-òî êîíöåïòóàëüíî íîâîå
• ïðîðàñòàåò âî âñå ïîäñèñòåìû
• ñëîæíî óáðàòü
12
Фундаментальный фреймворк
26. • äåëàåò ðàçðàáîòêó ïðîùå/ëó÷øå/áûñòðåå
• ïðèâíîñèò ÷òî-òî êîíöåïòóàëüíî íîâîå
• ïðîðàñòàåò âî âñå ïîäñèñòåìû
• ñëîæíî óáðàòü
• òðåáóåò íàâûêîâ îáðàùåíèÿ
12
Фундаментальный фреймворк
38. • onNext – 0, n èëè inf
• onCompleted – 0 èëè 1
17
Нотификации
39. • onNext – 0, n èëè inf
• onCompleted – 0 èëè 1
• onError – 0 èëè 1
17
Нотификации
40. • onNext – 0, n èëè inf
• onCompleted – 0 èëè 1
• onError – 0 èëè 1
• onCompleted + onError <= 1
17
Нотификации
42. • íå íóæíî îòïèñûâàòüñÿ ïîñëå çàâåðøåíèÿ
18
Подписка и отписка
43. • íå íóæíî îòïèñûâàòüñÿ ïîñëå çàâåðøåíèÿ
• ïðè îòïèñêå çàâåðøåíèå íå ãàðàíòèðîâàíî
18
Подписка и отписка
49. 24
Observable<Response> obs = Observable
.interval(1, TimeUnit.SECONDS)
.map(this ::sendPing)
.cache();
Subscription sub = obs.subscribe();
//позже
sub.unsubscribe();
50. 25
Observable<Response> obs = Observable
.interval(1, TimeUnit.SECONDS)
.map(this ::sendPing)
.cache();
Subscription sub = obs.subscribe();
//позже
sub.unsubscribe();
Note: You sacrifice the ability to
unsubscribe from the origin
51. 26
Observable<Response> obs = Observable
.interval(1, TimeUnit.SECONDS)
.map(this ::sendPing)
.cache();
Subscription sub = obs.subscribe();
//позже
sub.unsubscribe();
Note: You sacrifice the ability to
unsubscribe from the origin
55. • îòïðàâêà íîòèôèêàöèé
• çàâåðøåíèå ñ îøèáêîé
• ïîëíûé ñïèñîê : http://reactivex.io/documentation/contract.html
27
О контрактах
71. • ñîåäèíåíèå èìïåðàòèâíîãî è ðåàêòèâíîãî ìèðà
• êîãäà íåâîçìîæíî ñäåëàòü ïî äðóãîìó
• ýòî âàø ñëó÷àé? ÍÅÒ!
• âñå òàêè âàø? Íåò, ýòî íå òàê!
35
Subjects
72. • ñîåäèíåíèå èìïåðàòèâíîãî è ðåàêòèâíîãî ìèðà
• êîãäà íåâîçìîæíî ñäåëàòü ïî äðóãîìó
• ýòî âàø ñëó÷àé? ÍÅÒ!
• âñå òàêè âàø? Íåò, ýòî íå òàê!
• ìåíüøå – ëó÷øå
35
Subjects
77. • ïðîáëåìû
• íåò ïîíèìàÿ ðàáîòû
• ñóþò subscribeOn è observeOn âåçäå ïîäðÿä
37
О тредах
78. • ïðîáëåìû
• íåò ïîíèìàÿ ðàáîòû
• ñóþò subscribeOn è observeOn âåçäå ïîäðÿä
• âàæíî :
37
О тредах
79. • ïðîáëåìû
• íåò ïîíèìàÿ ðàáîòû
• ñóþò subscribeOn è observeOn âåçäå ïîäðÿä
• âàæíî :
• ðàçáèðàòüñÿ
37
О тредах
91. 45
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.map(this ::cacheAndModify);
//ui thread
requestObs.subscribe(this ::showOnUi);
92. 46
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.map(this ::cacheAndModify);
//ui thread
requestObs.subscribe(this ::showOnUi);
93. 47
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
94. 48
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
95. 49
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
96. 50
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
97. 51
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
98. 52
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
99. 53
Observable<Response> requestObs = userDbChanges
.filter(u -> u.age < 18)
.map(this ::toRequestModel)
.observeOn(networkScheduler)
.map(this ::doRequest)
.onErrorReturn(this ::doRecoverReq)
.subscribeOn(Schedulers.computation())
.observeOn(mainThread)
.map(this ::toUiModel);
//ui thread
requestObs.subscribe(this ::showOnUi);
110. 64
public class OperatorSubscribeOn<T> implements Operator<T, Observable<T >> {
private final Scheduler scheduler;
public OperatorSubscribeOn(Scheduler scheduler) {
this.scheduler = scheduler;
}
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
…
}
111. 65
public class OperatorSubscribeOn<T> implements Operator<T, Observable<T >> {
private final Scheduler scheduler;
public OperatorSubscribeOn(Scheduler scheduler) {
this.scheduler = scheduler;
}
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
…
}
принимаетвозвращает
112. 66
public class OperatorSubscribeOn<T> implements Operator<T, Observable<T >> {
private final Scheduler scheduler;
public OperatorSubscribeOn(Scheduler scheduler) {
this.scheduler = scheduler;
}
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
…
}
113. 67
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
114. 68
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
115. 69
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
116. 70
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
117. 71
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
Наш Observable
118. 72
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
119. 73
@Override
public Subscriber<? super Observable<T >> call(final Subscriber<? super T> subscriber) {
final Worker inner = scheduler.createWorker();
subscriber.add(inner);
return new Subscriber<Observable<T >>(subscriber) {
@Override
public void onNext(final Observable<T> o) {
inner.schedule(new Action0() {
@Override
public void call() {
final Thread t = Thread.currentThread();
o.unsafeSubscribe(new Subscriber<T>(subscriber) {
//обычный inner subscribe
}
//тут еще оооочень много закрывающихся скобочек
}
128. 82
//computation
Observable<Long> o1 = Observable.interval(1, TimeUnit.SECONDS);
//network
Observable<Integer> o2 = Observable.just(1)
.observeOn(networkScheduler);
Observable.zip(o1, o2, o3, (r1, r2) -> r1 * r2);
129. 83
//computation
Observable<Long> o1 = Observable.interval(1, TimeUnit.SECONDS);
//network
Observable<Integer> o2 = Observable.just(1)
.observeOn(networkScheduler);
Observable.zip(o1, o2, o3, (r1, r2) -> r1 * r2);
130. 84
//computation
Observable<Long> o1 = Observable.interval(1, TimeUnit.SECONDS);
//network
Observable<Integer> o2 = Observable.just(1)
.observeOn(networkScheduler);
Observable.zip(o1, o2, o3, (r1, r2) -> r1 * r2);
//computation or network
131. 85
final class InnerSubscriber extends Subscriber {
@Override
public void onNext(Object t) {
try {
items.onNext(t);
} catch (MissingBackpressureException e) {
onError(e);
}
tick();
}
};
132. 86
final class InnerSubscriber extends Subscriber {
@Override
public void onNext(Object t) {
try {
items.onNext(t);
} catch (MissingBackpressureException e) {
onError(e);
}
tick();
}
};
133. 87
void tick() {
//тут много кода, не имеющего сейчас значения
if (requested.get() > 0 && allHaveValues) {
try {
// всем потокам есть что zip’ать
child.onNext(zipFunction.call(vs));
}
// еще много кода и скобочки
134. 88
void tick() {
//тут много кода, не имеющего сейчас значения
if (requested.get() > 0 && allHaveValues) {
try {
// всем потокам есть что zip’ать
child.onNext(zipFunction.call(vs));
}
// еще много кода и скобочки
135. 89
void tick() {
//тут много кода, не имеющего сейчас значения
if (requested.get() > 0 && allHaveValues) {
try {
// всем потокам есть что zip’ать
child.onNext(zipFunction.call(vs));
}
// еще много кода и скобочки
141. • ïðîáëåìû:
• áîëüøå ýëåìåíòîâ – áîëüøå ìóñîðà
• RxJava ïîñòîÿííî âñå êîïèðóåò
92
Количество элементов
142. • ïðîáëåìû:
• áîëüøå ýëåìåíòîâ – áîëüøå ìóñîðà
• RxJava ïîñòîÿííî âñå êîïèðóåò
• âàæíî:
92
Количество элементов
143. • ïðîáëåìû:
• áîëüøå ýëåìåíòîâ – áîëüøå ìóñîðà
• RxJava ïîñòîÿííî âñå êîïèðóåò
• âàæíî:
• íå ïàíèêîâàòü
92
Количество элементов
144. • ïðîáëåìû:
• áîëüøå ýëåìåíòîâ – áîëüøå ìóñîðà
• RxJava ïîñòîÿííî âñå êîïèðóåò
• âàæíî:
• íå ïàíèêîâàòü
• çàáîòèòüñÿ î GC
92
Количество элементов
146. • «×òî ñ GC?» : ñàìûé æàðêèé âîïðîñ
93
Не паниковать
147. • «×òî ñ GC?» : ñàìûé æàðêèé âîïðîñ
• êîïèðîâàíèå òîëüêî ïðè íîòèôèêàöèÿõ
93
Не паниковать
148. • «×òî ñ GC?» : ñàìûé æàðêèé âîïðîñ
• êîïèðîâàíèå òîëüêî ïðè íîòèôèêàöèÿõ
• âñå îïòèìèçèðîâàííî
93
Не паниковать
161. • áåðåæåò GC
• áåðåæåò òðàôèê ïîëüçîâàòåëÿ
• áåðåæåò íàñ îò BackPressure
103
debounce
164. • îòäàþùèé òðåä äàåò ìíîãî
• ïðèíèìàþùèé òðåä íå óñïåâàåò
104
Backpressure
165. • îòäàþùèé òðåä äàåò ìíîãî
• ïðèíèìàþùèé òðåä íå óñïåâàåò
• â ìíîãîïîòî÷íîé ñðåäå ìíîãîâåðîÿòíî
104
Backpressure
166. • îòäàþùèé òðåä äàåò ìíîãî
• ïðèíèìàþùèé òðåä íå óñïåâàåò
• â ìíîãîïîòî÷íîé ñðåäå ìíîãîâåðîÿòíî
• ïåðâûé ïðèçíàê – observeOn
104
Backpressure
170. 108
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
171. 109
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
map
172. 110
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
map map
173. 111
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
map map subscriber
174. 112
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
map map subscriber
175. 113
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
map map subscriber
176. 114
events filter map observeOn
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
map map subscriber
177. 115
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
178. 116
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
179. 117
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
180. 118
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
181. 119
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
182. 120
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
183. 121
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
184. 122
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
185. 123
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
186. 124
events filter map observeOn
map map subscriber
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
187. 125
events filter map observeOn
map map subscriber
2
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
188. 126
events filter map observeOn
map map subscriber
2
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
189. 127
events filter map observeOn
map map subscriber
2
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
190. 128
events filter map observeOn
map map subscriber
2
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
191. 129
events filter map observeOn
map map subscriber
3
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
192. 130
events filter map observeOn
map map subscriber
3
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
193. 131
events filter map observeOn
map map subscriber
3
Устал
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
194. 132
events filter map observeOn
map map subscriber
3
Устал
touchEvents(view)
.filter(e -> e.x > minWidth)
.map(this ::normalize)
.observeOn(networkScheduler)
.map(this ::prepareForSending)
.map(this ::doMotionRequest)
.subscribe()
205. • debounce, throttle
• window, buffer
• onBackpressureBuffer
• onBackpressureDrop
139
Борьба с Backpressure
212. • íå áîéñÿ ðàñøèðÿòü ôðåéìâîðê
145
Как инженер
213. • íå áîéñÿ ðàñøèðÿòü ôðåéìâîðê
• ïîíèìàé, êàê îí ðàáîòàåò âíóòðè
145
Как инженер
216. • doOnNext == ñàéä ýôôåêò
• íå áëîêèðîâàòü âûïîëíåíèå ðîäèòåëÿ
146
DoOnNextAsync
217. • doOnNext == ñàéä ýôôåêò
• íå áëîêèðîâàòü âûïîëíåíèå ðîäèòåëÿ
• áûë ïðèâÿçàí ê æèçíåííîìó öèêëó ðîäèòåëÿ
146
DoOnNextAsync
218. • doOnNext == ñàéä ýôôåêò
• íå áëîêèðîâàòü âûïîëíåíèå ðîäèòåëÿ
• áûë ïðèâÿçàí ê æèçíåííîìó öèêëó ðîäèòåëÿ
• íå ÷åðåç Subjects
146
DoOnNextAsync
223. 151
class DoOnNextAsync<F, T> implements Observable.Operator<F, F> {
private final Func1<F, Observable<T >> nested;
public DoOnNextAsync(Func1<F, Observable<T >> func) {
this.nested = func;
}
//больше кода дальше
224. 152
class DoOnNextAsync<F, T> implements Observable.Operator<F, F> {
private final Func1<F, Observable<T >> nested;
public DoOnNextAsync(Func1<F, Observable<T >> func) {
this.nested = func;
}
//больше кода дальше
225. 153
class DoOnNextAsync<F, T> implements Observable.Operator<F, F> {
private final Func1<F, Observable<T >> nested;
public DoOnNextAsync(Func1<F, Observable<T >> func) {
this.nested = func;
}
//больше кода дальше
226. 154
@Override
public Subscriber<? super F> call(Subscriber<? super F> subscriber) {
return new Subscriber<F>() {
@Override
public void onNext(F next) {
if (!subscriber.isUnsubscribed()) {
Subscription s = nested.call(next).subscribe();
subscriber.add(s);
}
}
//тривиальные onError и onCompleted здесь
};
}
227. 155
@Override
public Subscriber<? super F> call(Subscriber<? super F> subscriber) {
return new Subscriber<F>() {
@Override
public void onNext(F next) {
if (!subscriber.isUnsubscribed()) {
Subscription s = nested.call(next).subscribe();
subscriber.add(s);
}
}
//тривиальные onError и onCompleted здесь
};
}
228. 156
@Override
public Subscriber<? super F> call(Subscriber<? super F> subscriber) {
return new Subscriber<F>() {
@Override
public void onNext(F next) {
if (!subscriber.isUnsubscribed()) {
Subscription s = nested.call(next).subscribe();
subscriber.add(s);
}
}
//тривиальные onError и onCompleted здесь
};
}
229. 157
@Override
public Subscriber<? super F> call(Subscriber<? super F> subscriber) {
return new Subscriber<F>() {
@Override
public void onNext(F next) {
if (!subscriber.isUnsubscribed()) {
Subscription s = nested.call(next).subscribe();
subscriber.add(s);
}
}
//тривиальные onError и onCompleted здесь
};
}
230. 158
@Override
public Subscriber<? super F> call(Subscriber<? super F> subscriber) {
return new Subscriber<F>() {
@Override
public void onNext(F next) {
if (!subscriber.isUnsubscribed()) {
Subscription s = nested.call(next).subscribe();
subscriber.add(s);
}
}
//тривиальные onError и onCompleted здесь
};
}
231. • Operator, lift,
• subscribeOn, observeOn
• nest, defer, create
159
Понимай, как работает внутри
236. • ñîåäèíÿòü èìïåðàòèâíûé è ðåàêòèâíûé ìèð
• íå èñïîëüçîâàòü ñàáäæåêòû
• îïèñûâàòü, «êàê äåëàòü», à íå «÷òî äåëàòü»
161
Думать реактивно
240. • íàó÷èòü RecycerView àâòîïîäãðóçêå
• ñäåëàòü ñ ïîìîùüþ RxJava
• â ðåàêòèâíîì ñòèëå
162
AutoLoadingRecyclerView
241. 163
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<Pair<Integer, Integer >> scrollLoadingChannel =
PublishSubject.create();
protected void startScrollingChannel() {
addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (shouldLoad()) {
int offset = getAdapter().getItemCount();
scrollLoadingChannel.onNext(new Pair(offset, limit));
}
}
});
}
242. 164
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<Pair<Integer, Integer >> scrollLoadingChannel =
PublishSubject.create();
protected void startScrollingChannel() {
addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (shouldLoad()) {
int offset = getAdapter().getItemCount();
scrollLoadingChannel.onNext(new Pair(offset, limit));
}
}
});
}
243. 165
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<Pair<Integer, Integer >> scrollLoadingChannel =
PublishSubject.create();
protected void startScrollingChannel() {
addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (shouldLoad()) {
int offset = getAdapter().getItemCount();
scrollLoadingChannel.onNext(new Pair(offset, limit));
}
}
});
}
244. 166
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<Pair<Integer, Integer >> scrollLoadingChannel =
PublishSubject.create();
protected void startScrollingChannel() {
addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (shouldLoad()) {
int offset = getAdapter().getItemCount();
scrollLoadingChannel.onNext(new Pair(offset, limit));
}
}
});
}
245. 167
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<Pair<Integer, Integer >> scrollLoadingChannel =
PublishSubject.create();
protected void startScrollingChannel() {
addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (shouldLoad()) {
int offset = getAdapter().getItemCount();
scrollLoadingChannel.onNext(new Pair(offset, limit));
}
}
});
}
246. 168
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<OffsetAndLimit> scrollLoadingChannel =
PublishSubject.create();
protected Subscription loadNewItemsSubscription;
protected Subscription subscribeToLoadingChannelSubscription;
247. 169
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<OffsetAndLimit> scrollLoadingChannel =
PublishSubject.create();
protected Subscription loadNewItemsSubscription;
protected Subscription subscribeToLoadingChannelSubscription;
248. 170
public class AutoLoadingRecyclerView<T> extends RecyclerView {
protected PublishSubject<OffsetAndLimit> scrollLoadingChannel =
PublishSubject.create();
protected Subscription loadNewItemsSubscription;
protected Subscription subscribeToLoadingChannelSubscription;
249. 171
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
250. 172
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
251. 173
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
252. 174
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
253. 175
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
254. 176
private static Observable<Integer>
getScrollObservable(RecyclerView recyclerView, int limit) {
return Observable.create(subscriber -> {
final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!subscriber.isUnsubscribed() && shouldLoad()) {
subscriber.onNext(recyclerView.getAdapter().getItemCount());
}
}
};
recyclerView.addOnScrollListener(sl);
subscriber.add(Subscriptions.create(() -> recyclerView.removeOnScrollListener(sl)));
});
}
265. • èñïîëüçîâàòü ñòàíäàðòíûå ñðåäñòâà RxJava
• íî íå ñàáäæåêòû
• ïðè íåîáõîäèìîñòè – ïèñàòü ñâîå
• îáîðà÷èâàòü ñîñòîÿíèå â Observable
183
Думать реактивно
266. • èñïîëüçîâàòü ñòàíäàðòíûå ñðåäñòâà RxJava
• íî íå ñàáäæåêòû
• ïðè íåîáõîäèìîñòè – ïèñàòü ñâîå
• îáîðà÷èâàòü ñîñòîÿíèå â Observable
• ñòàðàòüñÿ è íå ñäàâàòüñÿ
183
Думать реактивно
271. • äóìàòü î
• î êîíòðàêòàõ
• î òðåäàõ
• î êîëè÷åñòâå ýëåìåíòîâ
184
The Art of Rx
272. • äóìàòü î
• î êîíòðàêòàõ
• î òðåäàõ
• î êîëè÷åñòâå ýëåìåíòîâ
• äóìàòü êàê
184
The Art of Rx
273. • äóìàòü î
• î êîíòðàêòàõ
• î òðåäàõ
• î êîëè÷åñòâå ýëåìåíòîâ
• äóìàòü êàê
• èíæåíåð
184
The Art of Rx
274. • äóìàòü î
• î êîíòðàêòàõ
• î òðåäàõ
• î êîëè÷åñòâå ýëåìåíòîâ
• äóìàòü êàê
• èíæåíåð
• ðåàêòèâíî
184
The Art of Rx