SlideShare a Scribd company logo
1 of 193
Download to read offline
Реактивный двигатель вашего
Android приложения
Матвей Мальков
Обо мне
3
Обо мне
О чем доклад
5
• практика
6
О чем доклад
• практика
• проблемы
7
О чем доклад
• практика
• проблемы
• решения
8
О чем доклад
• практика
• проблемы
• решения
• android + RxJava
9
О чем доклад
Сейчас
11
User Interface
12
User Interface
TextView
EditText
EditText
Button Button
13
User Interface
TextView
EditText
EditText
Button Button
State
14
Data
15
Data
API
CacheDevice
DB
16
Data
State
API
CacheDevice
DB
17
Состояние системы
• мутабельно
18
Состояние системы
• мутабельно
• обновляется через callback
19
Состояние системы
• мутабельно
• обновляется через callback
• плохо композируется
20
Состояние системы
• мутабельно
• обновляется через callback
• плохо композируется
• явное
21
Состояние системы
Мутабельность
23
User user = new User("Jake Mobius");



/**

* 100 качественных строчек кода

*/



final String name = user.getName();

//этот assert легко может упасть

assert("Jake Mobius".equals(name));
24
// какой-то тред 

User user = new User("Jake Mobius");

fetchInfo(user);



final String name = user.getName();

//этот assert легко может упасть

assert("Jake Mobius".equals(name));
25
// какой-то тред 

User user = new User("Jake Mobius");

fetchInfo(user);



final String name = user.getName();

//этот assert легко может упасть

assert("Jake Mobius".equals(name));
// в это же время

// другой какой-то тред

user.setName("Jake Popik");
Обновляемость через callback
27
28
29
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

setHasDuplicates(calcDuplicates(response));

}

});

}

});

}

});
30
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

setHasDuplicates(calcDuplicates(response));

}

});

}

});

}

});
31
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

setHasDuplicates(calcDuplicates(response));

}

});

}

});

}

});
32
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

setHasDuplicates(calcDuplicates(response));

}

});

}

});

}

});
Плохая композируемость
34
35
passEditText.addTextChangedListener(new Watcher() {

@Override

public void afterTextChanged(Editable editable) {

lastPassText = editable.toString();

checkEqualityToEnableButton();

}

});



confirmEditText.addTextChangedListener(new Watcher() {

@Override

public void afterTextChanged(Editable editable) {

lastConfirmText = editable.toString();

checkEqualityToEnableButton();

}

});
36
passEditText.addTextChangedListener(new Watcher() {

@Override

public void afterTextChanged(Editable editable) {

lastPassText = editable.toString();

checkEqualityToEnableButton();

}

});



confirmEditText.addTextChangedListener(new Watcher() {

@Override

public void afterTextChanged(Editable editable) {

lastConfirmText = editable.toString();

checkEqualityToEnableButton();

}

});
37
38
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

lastIsNameEmpty = editable.toString().length() == 0;

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

lastIsHasDuplicates = calcDuplicates(response);

setHasDuplicates(lastIsHasDuplicates);

checkEqualityToEnableButton();

}

});

}

});

}

});
39
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

lastIsNameEmpty = editable.toString().length() == 0;

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

lastIsHasDuplicates = calcDuplicates(response);

setHasDuplicates(lastIsHasDuplicates);

checkEqualityToEnableButton();

}

});

}

});

}

});
40
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

lastIsNameEmpty = editable.toString().length() == 0;

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

lastIsHasDuplicates = calcDuplicates(response);

setHasDuplicates(lastIsHasDuplicates);

checkEqualityToEnableButton();

}

});

}

});

}

});
41
nameEditText.addTextChangedListener(new Watcher() {



@Override public void afterTextChanged(Editable editable) {

lastIsNameEmpty = editable.toString().length() == 0;

requestDuplicates(editable.toString(), new MyCallback() {



@Override public void onResponse(Response response){

checkResponseForDuplicates(response, new MyCallback() {



@Override public void onResponse(Response response) {

lastIsHasDuplicates = calcDuplicates(response);

setHasDuplicates(lastIsHasDuplicates);

checkEqualityToEnableButton();

}

});

}

});

}

});
Явное состояние
43
private String lastPassText;

private String lastConfirmText;

private boolean lastIsHasDuplicates;

private boolean lastIsNameEmpty;
44
lastPassText = editable.toString().trim();
45
lastPassText = editable.toString().trim();
46
lastPassText = editable.toString().trim();
47
private String lastPassText;

private String lastConfirmText;

private boolean lastIsHasDuplicates;

private boolean lastIsNameEmpty;



private String lastPassTrimmedString;
“Все может быть лучше”
“Пора стать реактивней”
50
Потоки данных
t
Данные Ошибка Конец
51
t
52
M
M
t
53
Mo
M Mo
t
54
Mob
M Mo Mob
t
55
Mobi
M Mo Mob Mobi
t
56
Mobiu
MobiuM Mo Mob Mobi
t
57
Mobius
MobiuM Mo Mob Mobi Mobius
t
• изолируют состояние
58
Потоки данных
• изолируют состояние
• прошлое
59
Потоки данных
• изолируют состояние
• прошлое
• настоящее
60
Потоки данных
• изолируют состояние
• прошлое
• настоящее
• будущее
61
Потоки данных
• изолируют состояние
• прошлое
• настоящее
• будущее
• неизменяемые
62
Потоки данных
• изолируют состояние
• прошлое
• настоящее
• будущее
• неизменяемые
• строго типизированные
63
Потоки данных
• EditTextObservable
64
Что может быть потоком?
• EditTextObservable
• ApiDataObservable
65
Что может быть потоком?
• EditTextObservable
• ApiDataObservable
• TouchObservable
66
Что может быть потоком?
• EditTextObservable
• ApiDataObservable
• TouchObservable
• Все, что захотите
67
Что может быть потоком?
RxJava
• reactive streams для java
69
RxJava
• reactive streams для java
• open source
• by Netflix
70
RxJava
• reactive streams для java
• open source
• by Netflix
• стабильная
71
RxJava
• reactive streams для java
• open source
• by Netflix
• стабильная
• почти
72
RxJava
Observable
74
Потоки данных
t
Данные Ошибка Конец
• создать
75
Observable можно
• создать
• изменить
76
Observable можно
• создать
• изменить
• получить значения
77
Observable можно
78
Создание
7
Observable<Integer> just = Observable.just(7);
t
79
Создание
6541 2 3 7
Observable<Integer> many = Observable

.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
t
80
Создание
Observable.create(subscriber -> {

final List<Data> list = requestNewData();



for (final Data data : list) {

subscriber.onNext(data);

}

subscriber.onCompleted();

});
81
Создание
Observable.create(subscriber -> {

final List<Data> list = requestNewData();



for (final Data data : list) {

subscriber.onNext(data);

}

subscriber.onCompleted();

});
82
Создание
Observable.create(subscriber -> {

final List<Data> list = requestNewData();



for (final Data data : list) {

subscriber.onNext(data);

}

subscriber.onCompleted();

});
83
Создание
Observable.create(subscriber -> {

final List<Data> list = requestNewData();



for (final Data data : list) {

subscriber.onNext(data);

}

subscriber.onCompleted();

});
84
Подписка
t
85
Подписка
Кто-то №1
t
86
Подписка
Кто-то №1
M
t
M
87
Подписка
Кто-то №2
M
t
Кто-то №1
M
88
Подписка
Кто-то №2
M Mo
t
Mo
Кто-то №1
89
Подписка
Кто-то №2
M Mo Mob
t
Mob
Кто-то №1
90
91
Observable<String> nameObs = EditTextObservable.from(nameEditText);



Subscription nameSubs = nameObs

.doOnNext(name -> {

Log.i(TAG, "new user name : " + name);

})

.subscribe(name -> {

signUpTitle.setText("Sign up, " + name);

});
92
Observable<String> nameObs = EditTextObservable.from(nameEditText);



Subscription nameSubs = nameObs

.doOnNext(name -> {

Log.i(TAG, "new user name : " + name);

})

.subscribe(name -> {

signUpTitle.setText("Sign up, " + name);

});
93
Observable<String> nameObs = EditTextObservable.from(nameEditText);



Subscription nameSubs = nameObs

.doOnNext(name -> {

Log.i(TAG, "new user name : " + name);

})

.subscribe(name -> {

signUpTitle.setText("Sign up, " + name);

});
94
// когда больше не надо слушать этот EditText

nameSubs.unsubscribe();
Observable<String> nameObs = EditTextObservable.from(nameEditText);



Subscription nameSubs = nameObs

.doOnNext(name -> {

Log.i(TAG, "new user name : " + name);

})

.subscribe(name -> {

signUpTitle.setText("Sign up, " + name);

});
95
Операторы
• возвращают новый Observable
97
Операторы
• возвращают новый Observable
• применяются ко всему потоку
98
Операторы
Основы : map и flatMap
100
102
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
103
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
104
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
105
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
106
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
107
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



nameObs.subscribe(name -> requestDuplicates(name));



Observable<String> rightTitleObservable = nameObs

.map(name -> {

if (TextUtils.isEmpty(name)) return name;

else return ", " + name;

});



rightTitleObservable.subscribe(name ->

signUpTitle.setText("Sign up" + name));
108
109
110
Debounce
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);



duplicatesCheckObservable.subscribe(isUnique -> { /*process*/ });
111
Debounce
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);



duplicatesCheckObservable.subscribe(isUnique -> { /*process*/ });
112
Debounce
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);



duplicatesCheckObservable.subscribe(isUnique -> { /*process*/ });
113
Debounce
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);



duplicatesCheckObservable.subscribe(isUnique -> { /*process*/ });
• выполняется когда надо
114
Наше решение
• выполняется когда надо
• экономит траффик
115
Наше решение
• выполняется когда надо
• экономит траффик
• не нагружает сервер
116
Наше решение
• выполняется когда надо
• экономит траффик
• не нагружает сервер
• без callback hell
117
Наше решение
• выполняется когда надо
• экономит траффик
• не нагружает сервер
• без callback hell
• легко обрабатывает ошибки
118
Наше решение
119
Прочие полезности
• debounce
121
Полезности
• debounce
• cache
122
Полезности
• debounce
• cache
• timeout
123
Полезности
• debounce
• cache
• timeout
• first
124
Полезности
• debounce
• cache
• timeout
• first
• distinct
125
Полезности
• debounce
• cache
• timeout
• first
• distinct
• skipLast
126
Полезности
• debounce
• cache
• timeout
• first
• distinct
• skipLast
• reduce
127
Полезности
• debounce
• cache
• timeout
• first
• distinct
• skipLast
• reduce
• cast
128
Полезности
• debounce
• cache
• timeout
• first
• distinct
• skipLast
• reduce
• cast
• averageDouble
129
Полезности
• debounce
• cache
• timeout
• first
• distinct
• skipLast
• reduce
• cast
• averageDouble
• takeWhile
130
Полезности
Комбинирование
132
133
134
Observable<Boolean> shouldEnableButtonObs = Observable

.combineLatest(

passObs.map(pass -> pass.trim()),

confirmObs.map(confirm -> confirm.trim()),

duplicatesCheckObservable,

(pass, confirmPass, isNameUnique) ->

TextUtils.equals(pass, confirmPass)

&& isNameUnique

);



shouldEnableButtonObs

.subscribe(enabled -> button.setEnabled(enabled));
135
Observable<Boolean> shouldEnableButtonObs = Observable

.combineLatest(

passObs.map(pass -> pass.trim()),

confirmObs.map(confirm -> confirm.trim()),

duplicatesCheckObservable,

(pass, confirmPass, isNameUnique) ->

TextUtils.equals(pass, confirmPass)

&& isNameUnique

);



shouldEnableButtonObs

.subscribe(enabled -> button.setEnabled(enabled));
136
Observable<Boolean> shouldEnableButtonObs = Observable

.combineLatest(

passObs.map(pass -> pass.trim()),

confirmObs.map(confirm -> confirm.trim()),

duplicatesCheckObservable,

(pass, confirmPass, isNameUnique) ->

TextUtils.equals(pass, confirmPass)

&& isNameUnique

);



shouldEnableButtonObs

.subscribe(enabled -> button.setEnabled(enabled));
137
Observable<Boolean> shouldEnableButtonObs = Observable

.combineLatest(

passObs.map(pass -> pass.trim()),

confirmObs.map(confirm -> confirm.trim()),

duplicatesCheckObservable,

(pass, confirmPass, isNameUnique) ->

TextUtils.equals(pass, confirmPass)

&& isNameUnique

);



shouldEnableButtonObs

.subscribe(enabled -> button.setEnabled(enabled));
138
Observable<Boolean> shouldEnableButtonObs = Observable

.combineLatest(

passObs.map(pass -> pass.trim()),

confirmObs.map(confirm -> confirm.trim()),

duplicatesCheckObservable,

(pass, confirmPass, isNameUnique) ->

TextUtils.equals(pass, confirmPass)

&& isNameUnique

);



shouldEnableButtonObs

.subscribe(enabled -> button.setEnabled(enabled));
139
А сколько у нас явного состояния?
141
// нисколько
• полезно знать все
142
Операции
• полезно знать все
• применение есть всем. Ищите!
143
Операции
• полезно знать все
• применение есть всем. Ищите!
• смотрите исходники
144
Операции
• полезно знать все
• применение есть всем. Ищите!
• смотрите исходники
• думайте!
145
Операции
Когда тредов > 1
Scheduler
• имеет пул потоков
148
Scheduler
• имеет пул потоков
• создает Scheduler.Worker
149
Scheduler
• имеет пул потоков
• создает Scheduler.Worker
• Worker –– цепочка последовательных
вычислений
150
Scheduler
subscribeOn
observeOn
1. observeOn для того,
что ниже по коду
2. subscribeOn для того,
что выше по коду
3. Каждый следующий observeOn
заменяет предыдущий
4. subscribeOn актуален только до
первого observeOn
Оба оператора все еще возвращают
новый поток
157
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);

158
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.onErrorReturn(throwable -> false);

159
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

160
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

161
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

162
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

163
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

164
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

165
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);

166
Observable<Boolean> duplicatesCheckObservable = nameObs

.debounce(500, TimeUnit.MILLISECONDS)

.observeOn(Schedulers.newThread())

.map(name -> requestDuplicates(name))

.map(response -> checkResponseForDuplicates(response))

.map(checkedResp -> calcDuplicates(checkedResp))

.subscribeOn(mainThread)

.observeOn(mainThread)

.onErrorReturn(throwable -> false);



duplicatesCheckObservable.subscribe(isUnique -> { /*process*/ });
Ложечка дегтя
• объектов аллоцируется больше
168
Ложечка дегтя
• объектов аллоцируется больше
• сложно дебажить
169
Ложечка дегтя
• объектов аллоцируется больше
• сложно дебажить
• логируйте много
170
Ложечка дегтя
• объектов аллоцируется больше
• сложно дебажить
• логируйте много
• пишите правильно сразу
171
Ложечка дегтя
• объектов аллоцируется больше
• сложно дебажить
• логируйте много
• пишите правильно сразу
• сложно объяснить
172
Ложечка дегтя
• объектов аллоцируется больше
• сложно дебажить
• логируйте много
• пишите правильно сразу
• сложно объяснить
• сложно найти крутую команду
173
Ложечка дегтя
Итоги
• изолированное состояние
175
Итоги
• изолированное состояние
• легкая многопоточность
176
Итоги
• изолированное состояние
• легкая многопоточность
• легкое комбинирование
177
Итоги
• изолированное состояние
• легкая многопоточность
• легкое комбинирование
• понятность кода
178
Итоги
• изолированное состояние
• легкая многопоточность
• легкое комбинирование
• понятность кода
• стойкость к ошибкам
179
Итоги
Reactive Extension
Reactive Extension
Reactive Extension
Это круто!
Меняйтесь
За этим будущее
Спасибо
Матвей Мальков
malkov.matvey@gmail.com
matveyka_jj
Правильная реализация подсветки
кнопки
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable2 = nameObs

.flatMap(name ->

DebouncedDuplicatesObservable

.from(name)

.startWith(false))

.onErrorReturn(thr -> false);



duplicatesCheckObservable2.

subscribe(isDubl -> { /*process*/ });
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable2 = nameObs

.flatMap(name ->

DebouncedDuplicatesObservable

.from(name)

.startWith(false))

.onErrorReturn(thr -> false);



duplicatesCheckObservable2.

subscribe(isDubl -> { /*process*/ });
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable2 = nameObs

.flatMap(name ->

DebouncedDuplicatesObservable

.from(name)

.startWith(false))

.onErrorReturn(thr -> false);



duplicatesCheckObservable2.

subscribe(isDubl -> { /*process*/ });
Observable<String> nameObs = EditTextObservable

.from(nameEditText);



Observable<Boolean> duplicatesCheckObservable2 = nameObs

.flatMap(name ->

DebouncedDuplicatesObservable

.from(name)

.startWith(false))

.onErrorReturn(thr -> false);



duplicatesCheckObservable2.

subscribe(isDubl -> { /*process*/ });
• Reactive Streams
• Akka Stream
• Reactor
• Ratpack
• RxJava
• Reactive Manifesto
192
Ссылки
• Reactive Extensions
• Reactive Extensions for JavaScript
• Reactive Cocoa
• Rx.py
• Rx.php
193
Ссылки

More Related Content

What's hot

«Опыт использования каналов в корутинах в боевом проекте» Григорий Федоров
 «Опыт использования каналов в корутинах в боевом проекте»  Григорий Федоров «Опыт использования каналов в корутинах в боевом проекте»  Григорий Федоров
«Опыт использования каналов в корутинах в боевом проекте» Григорий ФедоровMail.ru Group
 
Экстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java DriverЭкстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java DriverVitebsk DSC
 
Михаил Давыдов: JavaScript. Асинхронность
Михаил Давыдов: JavaScript. АсинхронностьМихаил Давыдов: JavaScript. Асинхронность
Михаил Давыдов: JavaScript. АсинхронностьYandex
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETDev2Dev
 
WebCamp: Developer Day: Parse'им бэкенд - Аким Халилов
WebCamp: Developer Day: Parse'им бэкенд - Аким ХалиловWebCamp: Developer Day: Parse'им бэкенд - Аким Халилов
WebCamp: Developer Day: Parse'им бэкенд - Аким ХалиловGeeksLab Odessa
 
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)Ontico
 
Поиск наизнанку
Поиск наизнанкуПоиск наизнанку
Поиск наизнанкуNikolay Sivko
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + RetrofitDev2Dev
 
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...Ontico
 
Atomics, CAS and Nonblocking algorithms
Atomics, CAS and Nonblocking algorithmsAtomics, CAS and Nonblocking algorithms
Atomics, CAS and Nonblocking algorithmsAlexey Fyodorov
 
React со скоростью света: не совсем обычный серверный рендеринг
React со скоростью света: не совсем обычный серверный рендерингReact со скоростью света: не совсем обычный серверный рендеринг
React со скоростью света: не совсем обычный серверный рендерингTimophy Chaptykov
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ontico
 
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Ontico
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIPavel Asanov
 
Reactive programming для успеха вашего стартапа
Reactive programming для успеха вашего стартапаReactive programming для успеха вашего стартапа
Reactive programming для успеха вашего стартапаVitebsk DSC
 
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Ontico
 
Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015Mikhail Salosin
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)Mikhail Davydov
 
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...Ontico
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервереYandex
 

What's hot (20)

«Опыт использования каналов в корутинах в боевом проекте» Григорий Федоров
 «Опыт использования каналов в корутинах в боевом проекте»  Григорий Федоров «Опыт использования каналов в корутинах в боевом проекте»  Григорий Федоров
«Опыт использования каналов в корутинах в боевом проекте» Григорий Федоров
 
Экстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java DriverЭкстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java Driver
 
Михаил Давыдов: JavaScript. Асинхронность
Михаил Давыдов: JavaScript. АсинхронностьМихаил Давыдов: JavaScript. Асинхронность
Михаил Давыдов: JavaScript. Асинхронность
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
 
WebCamp: Developer Day: Parse'им бэкенд - Аким Халилов
WebCamp: Developer Day: Parse'им бэкенд - Аким ХалиловWebCamp: Developer Day: Parse'им бэкенд - Аким Халилов
WebCamp: Developer Day: Parse'им бэкенд - Аким Халилов
 
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
 
Поиск наизнанку
Поиск наизнанкуПоиск наизнанку
Поиск наизнанку
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + Retrofit
 
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
 
Atomics, CAS and Nonblocking algorithms
Atomics, CAS and Nonblocking algorithmsAtomics, CAS and Nonblocking algorithms
Atomics, CAS and Nonblocking algorithms
 
React со скоростью света: не совсем обычный серверный рендеринг
React со скоростью света: не совсем обычный серверный рендерингReact со скоростью света: не совсем обычный серверный рендеринг
React со скоростью света: не совсем обычный серверный рендеринг
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
 
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST API
 
Reactive programming для успеха вашего стартапа
Reactive programming для успеха вашего стартапаReactive programming для успеха вашего стартапа
Reactive programming для успеха вашего стартапа
 
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
 
Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)
 
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере
 

Similar to Реактивный двигатель вашего Android приложения

BDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehaveBDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehaveSQALab
 
Формальная верификация кода на языке Си
Формальная верификация кода на языке СиФормальная верификация кода на языке Си
Формальная верификация кода на языке СиPositive Development User Group
 
Formal verification of C code
Formal verification of C codeFormal verification of C code
Formal verification of C codeDenis Efremov
 
Формальная верификация кода на языке Си
Формальная верификация кода на языке СиФормальная верификация кода на языке Си
Формальная верификация кода на языке СиPositive Hack Days
 
Как приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложенияхКак приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложенияхDenis Tsvettsih
 
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)Ontico
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!RAMBLER&Co
 
RESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentationRESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentationMikhail Shcherbakov
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actualYevgen Levik
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyRegn
 
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...Ontico
 
Как приручить реактивное программирование
Как приручить реактивное программированиеКак приручить реактивное программирование
Как приручить реактивное программированиеDenis Tsvettsih
 
Референсная архитектура приложения на ASP.NET MVC
Референсная архитектура приложения на ASP.NET MVCРеференсная архитектура приложения на ASP.NET MVC
Референсная архитектура приложения на ASP.NET MVCAndrew Mayorov
 
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...Alexey Makhov
 
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидацииОмские ИТ-субботники
 
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»Yulia Tsisyk
 
Евгений Ртищев "Мобильная платформа на ReactNative"
Евгений Ртищев "Мобильная платформа на ReactNative"Евгений Ртищев "Мобильная платформа на ReactNative"
Евгений Ртищев "Мобильная платформа на ReactNative"IT Event
 
Что могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиЧто могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиAndrey Karpov
 
JPoint 2017 - Where is my service, dude?
JPoint 2017 - Where is my service, dude?JPoint 2017 - Where is my service, dude?
JPoint 2017 - Where is my service, dude?Viet Nguyen
 
Вадим Макишвили "Вёрстка в IntelliJIDEA"
Вадим Макишвили "Вёрстка в IntelliJIDEA"Вадим Макишвили "Вёрстка в IntelliJIDEA"
Вадим Макишвили "Вёрстка в IntelliJIDEA"Yandex
 

Similar to Реактивный двигатель вашего Android приложения (20)

BDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehaveBDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehave
 
Формальная верификация кода на языке Си
Формальная верификация кода на языке СиФормальная верификация кода на языке Си
Формальная верификация кода на языке Си
 
Formal verification of C code
Formal verification of C codeFormal verification of C code
Formal verification of C code
 
Формальная верификация кода на языке Си
Формальная верификация кода на языке СиФормальная верификация кода на языке Си
Формальная верификация кода на языке Си
 
Как приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложенияхКак приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложениях
 
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)
Переход с Objective-C на Swift — все ли так просто? / Олег Алексеенко (SuperJob)
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!
 
RESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentationRESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentation
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
 
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...
Длинная транзакция или когда размер имеет значение / Михаил Балаян (Odin — In...
 
Как приручить реактивное программирование
Как приручить реактивное программированиеКак приручить реактивное программирование
Как приручить реактивное программирование
 
Референсная архитектура приложения на ASP.NET MVC
Референсная архитектура приложения на ASP.NET MVCРеференсная архитектура приложения на ASP.NET MVC
Референсная архитектура приложения на ASP.NET MVC
 
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...
Прокачиваем WebDriverAgent или как тестировать iOS-приложения после ядерного ...
 
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации
2017-02-04 03 Алексей Букуров, Игорь Циглер. DSL для правил валидации
 
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»
Юлия Цисык «RESTFul API в вашем.NET приложении: как, зачем и почему?»
 
Евгений Ртищев "Мобильная платформа на ReactNative"
Евгений Ртищев "Мобильная платформа на ReactNative"Евгений Ртищев "Мобильная платформа на ReactNative"
Евгений Ртищев "Мобильная платформа на ReactNative"
 
Что могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиЧто могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщики
 
JPoint 2017 - Where is my service, dude?
JPoint 2017 - Where is my service, dude?JPoint 2017 - Where is my service, dude?
JPoint 2017 - Where is my service, dude?
 
Вадим Макишвили "Вёрстка в IntelliJIDEA"
Вадим Макишвили "Вёрстка в IntelliJIDEA"Вадим Макишвили "Вёрстка в IntelliJIDEA"
Вадим Макишвили "Вёрстка в IntelliJIDEA"
 

Реактивный двигатель вашего Android приложения