Pull to refresh

Comments 28

Я бы перевёл to grok как «раздуплять» =)
Лучше уж «вникать».
Слово to grok изобретено Хайнлайном и имеет два смысла: 1) понять во всей максимально возможной полноте и 2) съесть (по сюжету романа эти два значения связаны между собой). Так что переводчики романа (равно как и вы) поступили совершенно правильно, изобретя аналогичное слово для русского языка.
В русском "поведать" и "отведать" — так же весьма близкие, однокоренные слова...
Отличная статья, благодарю! Вот только один маленький нюанс — почему нигде не используется более краткая запись для лямбд — указатели на методы? С ними было бы ещё компактней и даже читабельней, как по мне...
Последнее время много слышу про Reactive и т.д.
А вот в чем отличие от Java 8 Streams? Все ваши примеры в статье можно заменить на Streams.
Java 8 Streams работают с Iterable, то есть Streams сами вытягивают данные, Pull API. В то время как в Rx (RxJava) Observable сам уведомляет о следующем событии (ошибка, новый элемент или конец потока), то есть это Push API.

Кроме того, Rx — это больше про бизнес логику, обработку данных, переключение между потоками и вот это всё, в то время как Streams это про функциональные операции над коллекциями/потоками данных.

Скажем, попробуйте с помощью Streams сделать такую вещь: сетевой запрос, который сначала вернёт локальный кеш (если он есть), потом сходит в сеть, вернёт результат из сети (и положит его в кеш), причём всё это на бэкграунд потоке(ах), а слушатель на UI потоке + обработка ошибок. Я не спорю, что это можно сделать на Streams с такой-то матерью, но Rx для подобных вещей гораздо удобнее.
В кратце, я бы сказал, что Streams — для работы с коллекциями (по цепочке), rx — для работы с событиями (по цепочке). При том что у rx намного богаче функциональность.
Помимо вышеперечисленного:
Для Android нет Java 8 и ее Streams, даже если использовать Retrolambda.
Еще для Android есть RxBinding либы для различных виджетов, которые так же дают много вкусняшек и завязаны на RxJava.
Может конечно придираюсь, но

> Задача этого цикла статей состоит не в том, чтобы объяснить всё вплоть до последней запятой (вряд ли я смог бы это сделать), но, скорее в том, чтобы заинтересовать вас RxJava, и тем, как она работает.

И сразу понеслись примеры кода…
А где объяснение, что это вообще такое ваш RxJava и для чего его придумали?
Придумали для того чтоб реалзовать парадигму реактивного программирования.
Суть — передавать события по цепочке со всевозможными трансформациями по пути. Абстрактный пример — представте таблицу Excel. Вы изменили ячейку — это начальное событие. Но от этой ячейки зависит значение других ячеек — они слушают событие от первой ячейки, применяют его и рассылают событие что они изменились. У них так же могут быть слушатели… Это простой пример реализации реактивного программирования.
Многопоточное приложение — что будет, после того, как в 1-й ячейке изменились данные и информация была реактивно передана дальше и, что будет, если в момент реактивного изменения второй ячейки, произойдет изменение данных в 1-ой? Будет новая итерация всей системы и зачем это нужно? Или, чем закончится изменение 3-й ячейки в 1-й итерации, если данные уже изменились? Может быть лучше применить шину данных (Otto, к примеру), где все слушатели получают актуальные, в настоящий момент, данные, не зависимо от состояния системы в целом.
Нет никаких ячеек :)

Для таких случаев есть операторы, которые позволяют обрабатывать группы событий: Debounce, Window, Buffer и тд.

Event bus тут ничем не отличается, собственно, Observable (PublishSubject) может заменить Event Bus полностью.
Ячейки — ответ на пост MercurieVV.
В том то и вопрос, почему не использовать Event Bus? Это дешевле в размере, производительности и меньше есть батарейку.
Ну, если вам его хватает — отлично :)
Я здесь потому, что мне не хватает того, что я использую…
Группа событий — это аналог транзакций? Могу ли я получить ответ на свой вопрос? Вы готовы ответить, что будет, если данные изменятся динамически в другом потоке? Как RxJava это регламентирует?
Исходя из простого примера с ячейками в ехеl.
Группа событий — это аналог транзакций?

Nope. Смотрите, в Rx (да и не только) есть такое понятие — Backpressure. Это когда у вас поток событий большой и они поступают быстрее, чем вы их обрабатываете. Для борьбы с Backpressure или просто для утихомиривания резкого потока событий в Rx есть несколько полезных операторов:

Debounce — скажем, пользователь вводит текст в поле, вы на это шлёте запросы в сеть, но вы не хотите на каждый символ этого делать если пользователь быстро вводит текст, тогда Debounce ваш друг — вы указываете временное окно, скажем, 300 мс и Debounce вернет вам результат только если после последнего события прошло 300 мс, то есть вы отфильтруете частые нажатия.

Filter — простейший оператор, в котором вы можете по какой-то вашей логике пропускать часть событий.

Buffer — оператор, которому вы говорите, а группируй мне события по 10 штук (или сколько нужно) и отправляй списком, а не по отдельности.

Window — похож на Buffer, но группирует события по временному промежутку, скажем, 500 мс, etc.

И тд., всякие OnBackpressureDrop, etc, очень рекомендую посмотреть документацию с прекрасными иллюстрациями: reactivex.io

Могу ли я получить ответ на свой вопрос?

Да :)

Вы готовы ответить, что будет, если данные изменятся динамически в другом потоке?

Готов :)

Как RxJava это регламентирует?

Как напишите, так и будет работать, зависит от примененных операторов. Вы можете добиться любого нужного вам поведения, причём, довольно элегантно.

Нужно отреагировать на все события — реагируйте, нужно пропустить близкие по времени события или сгруппировать и обработать их пачкой — пожалуйста, все возможности Rx перед вами, нужно лишь понять и прочитать документацию: reactivex.io

P.S.
Кстати, приходите на Yandex Mobile Camp 12 сентября (суббота) в Москве или на трансляцию в Новосибирске или Нижнем Новгороде, поговорим про Rx events.yandex.ru/events/yamobcamp :)
Во первых, хочу отметить что пример с Экселем — абстрактный пример что такое реактивное программирование, а не как работает rxJava
Ну а если говорить о rxJava, то ее суть — шина/цепочка/pipeline событий. Очень желательно чтоб передаваемые данные были immutable, иначе вся ответственность за его изменения ложится на вас.
Возьмем ваш пример применительно к rxJava.
Простейшая реализация:
Такт 1) Ячейка (испускатель событий) 1, испускает событие со своим новым значением.
Такт 2) Оно попадает в ячейку 2. Она его обрабатывает. В момент обработки, ячейка 1 испускает новый объект данных.
Такт 3) В ячейку 2 приходят новые данные. Она их обрабатывает.

Реализация с backpressure buffer:
Такт 1) Ячейка (испускатель событий) 1, испускает событие со своим новым значением. Буффер ловит его и держит у себя не отпуская дальше.
Такт 2) Я1 испускает новое событие. Буффер опять его ловит.
… какое-то время спустя
Такт N) Буффер все накопленные событие кладет в список и передает его как список в Я2

У rxJava очень наглядные картинки по каждому оператору. Посмотрите например
на debounce (раскройте там список rxJava в language specific) reactivex.io/documentation/operators/debounce.html#collapseRxJava
и group reactivex.io/documentation/operators/buffer.html
Интересно, насколько близка эта концепция к "сигналам-слотам" на Qt. Спасибо за статью.
Sign up to leave a comment.

Articles