Операторы используются для решения проблемы преобразования наблюдаемых объектов. Операторы используются для изменения событий, испускаемых наблюдаемыми между наблюдаемым и конечным подписчиком. Rxjava предоставляет много полезных операторов.
Например, оператор карты используется для преобразования одного события в другое.
Visemble.just ("hello, world!") .Map (new func1 <string, string> () {@override public String Call (String s) {return s + "-dan";}}) .subscribe (s -> system.out.println (s)); Использование Lambda может быть упрощено до
Visemble.just ("Привет, мир!") .Map (s -> s + "-dan") .subscribe (s -> system.out.println (s));Разве это не круто? Оператор MAP () используется для преобразования наблюдаемого объекта. Оператор карты возвращает наблюдаемый объект, чтобы можно было реализовать цепный вызов, а оператор карты используется несколько раз на наблюдаемом объекте, и, наконец, простые данные передаются объекту подписчика.
карта оператор продвинулся
Что более интересно в операторе карты, так это то, что он не должен возвращать тип, возвращаемый наблюдаемым объектом. Вы можете использовать оператор карты для возврата наблюдаемого объекта, который издает новый тип данных.
Например, в приведенном выше примере абонент не заботится о возвращаемой строке, но хочет хеш -значение строки.
Visemble.just ("Привет, мир!") .Map (новый func1 <string, integer> () {@override public integer call (string s) {return s.hashcode ();}}) .subscribe (i -> system.out.println (integer.tostring (i))); Очень интересно, верно? Наш первоначальный наблюдаемый возвращает строку, в то время как последний абонент получает целое число. Конечно, использование Lambda может еще больше упростить код:
Visemble.just ("Привет, мир!") .Map (s -> s.hashcode ()) .subscribe (i -> system.out.println (integer.tostring (i))); Как упоминалось ранее, чем меньше подписывается, тем лучше. Давайте добавим еще одного оператора карты.
Visemble.just ("Привет, мир!") .Map (s -> s.hashcode ()) .map (i -> integer.tostring (i)) .subscribe (s -> system.out.println (s)); Не убежден?
Как вы думаете, наш пример слишком прост, чтобы убедить вас? Вам нужно понять следующие два момента:
1. Наблюдаемый и абонент может сделать что угодно
Наблюдаемый может быть запросом базы данных, а подписчик используется для отображения результатов запроса; Наблюдаемое может быть событием Click на экране, а подписчик используется для реагирования на события клика; Наблюдаемый может быть сетевым запросом, а подписчик используется для отображения результатов запроса.
2. Наблюдаемый и подписчик не зависят от процесса промежуточного преобразования.
Любое количество карт может быть добавлено или уменьшено между наблюдаемым и подписчиком. Вся система очень комбинируется, а эксплуатационные данные - очень простой процесс.
Пример
1. Подготовка
Предположим, у меня есть такой метод:
Этот метод возвращает список URL -адресов веб -сайта на основе строки ввода (Ahha, поисковая система)
Наблюдаемый <список <string >> Query (строка текста);
Теперь я хочу создать надежную систему, которая может запросить струны и отображать результаты. Основываясь на содержании предыдущего блога, мы можем написать следующий код:
Query ("Привет, мир!") .subscribe (urls -> {for (string url: urls) {System.out.println (url);}});Конечно, этот вид кода не может быть допущен, потому что вышеупомянутый код заставил нас потерять возможность изменить поток данных. Как только мы хотим изменить каждый URL, мы можем сделать это только в подписчике. Мы не использовали такую классную карту () оператор! ! !
Конечно, я могу использовать оператор карты. Ввод карты - это список URL. При обработке все еще нужно пересекать каждого, что также очень болезненно.
К счастью, существует также метод наблюдаемого. От (), который получает коллекцию в качестве входного ввода, а затем выводит элемент для подписчика одновременно:
Usearble.from ("url1", "url2", "url3") .subscribe (url -> system.out.println (url)); Давайте только сейчас используем этот метод на сцене:
Query ("Привет, мир!") .subscribe (urls -> {visefable.from (urls) .subscribe (url -> system.out.println (url));});
Хотя для каждого цикла удаляется, код все еще выглядит грязно. Многочисленные вложенные подписки не только выглядят не только уродливыми и трудно изменить, но и более серьезно, это разрушит некоторые особенности Rxjava, которые мы еще не упомянули.
2. Улучшение
Спаситель здесь, он плоская карта ().
Usemberble.flatmap () получает выходной сигнал наблюдаемого ввода в качестве входного и выводит другой наблюдаемый одновременно. Посмотрите прямо на код:
Query ("Привет, World!") .flatmap (новый Func1 <list <string>, наблюдаемый <string >> () {@Override public usebreable <string> call (list <string> urls) {return vasemable.from (urls);}}) .subscribe (url -> system.out.println (url);}); Здесь я опубликовал весь код функции, чтобы помочь вам понять, что происходит. Использование Lambda может значительно упростить длину кода:
Query ("Привет, мир!") .flatmap (urls -> visemble.from (urls)) .subscribe (url -> system.out.println (url));Flatmap () выглядит странно? Почему он возвращает еще один наблюдаемый? Ключевой момент в понимании плоской карты заключается в том, что новый наблюдаемый выход из Flatmap является именно тем, что мы хотим получить в подписчике. Теперь абонент больше не получает список <String>, но вместо этого получает некоторые отдельные строки столбцов, как и выходной сигнал. От ().
Эта часть также является самой сложной частью, когда я впервые выучил rxjava. Как только я вдруг понял это, многие из вопросов в Rxjava были решены.
3. Это может быть лучше
Flatmap () на самом деле не лучшая идея, он может вернуть любой наблюдаемый объект, который он хочет вернуть.
Например, следующий метод:
// возвращать заголовок веб -сайта, и если это 404, вернуть NULL Observable <string> getTitle (string url);
Следуя предыдущему примеру, теперь я больше не хочу печатать URL -адрес, но вместо этого печатайте название каждого веб -сайта, который я получаю. Проблема в том, что мой метод может проходить только в одном URL -адресу за раз, а возвратное значение не является строкой, а наблюдающим объектом, который выводит строку. Использование flatmap () может просто решить эту проблему.
Query ("Привет, World!") .flatmap (urls -> visionable.from (urls)) .flatmap (new func1 <string, visionable <string >> () {@override public usebreable <string> call (string url) {return getTitle (url);}}}) .subscribe (title stystem.out.out.out.out.out.out.out.out.out.out. 4. Используйте Lambda:
Query ("Привет, мир!") .flatmap (urls -> visemble.from (urls)) .flatmap (url -> getTitle (url)) .subscribe (title -> system.out.println (title)); Разве это не чувствует себя невероятно? Я на самом деле могу объединить несколько независимых методов для возврата наблюдаемых объектов вместе! Очень красиво!
Более того, я также объединил вызовы двух API в прикол. Мы можем связать как можно больше вызовов API. Каждый должен знать, как больно синхронизировать все вызовы API, а затем объединить результаты обратного вызова всех вызовов API в данные, которые будут отображаться. Здесь мы успешно избежали ада обратного вызова (многослойные вложенные обратные вызовы, что затрудняет чтение и поддержание кода). Теперь вся логика обернута в этот простой отзывчивый вызов.
5. Богатые операторы <br /> До сих пор мы вступили в контакт с двумя операторами, и в Rxjava больше операторов, так как мы используем другие операторы для улучшения нашего кода?
getTitle () возвращает NULL, если URL не существует. Мы не хотим выводить «NULL», тогда мы можем отфильтровать нулевое значение из возвращенного списка заголовков!
Query ("Привет, мир!") .flatmap (urls -> visemble.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .subscribe (title -> System.out.println (title));Filter () выводит те же элементы, что и ввод, и фильтруют те, которые не соответствуют критериям проверки.
Если мы хотим только до 5 результатов:
Query ("Привет, мир!") .flatmap (urls -> visemble.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .take (5) .subscribe (title -> System.out.println (Title));Take () выводит максимальное количество результатов.
Если мы хотим сохранить каждый заголовок на диск перед печати:
Query ("Привет, мир!") .flatmap (urls -> visionable.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .take (5) .doonnext (title -> savetitle (title) .subscribe (title- system.out.DOONNEXT () позволяет нам делать несколько дополнительных вещей, прежде чем выводить элемент за раз, например, сохранить заголовок здесь.
Легко ли увидеть, как легко управлять потоком данных здесь? Вы можете добавить столько операций, сколько захотите, и не испортить свой код.
Rxjava содержит большое количество операторов. Количество операторов немного страшное, но стоит проверить один за другим, чтобы вы могли знать, какие операторы могут быть использованы. Может потребоваться некоторое время, чтобы понять этих операторов, но как только вы поймете, вы полностью поймете силу Rxjava.
Вы даже можете написать пользовательские операторы! Этот блог не намеревается настроить оператора. Если вы хотите, пожалуйста, Google это сами.
Как вы себя чувствуете?
Ну, вы скептик, и это трудно убедить, так почему вы заботитесь об этих операторах?
Потому что операторы позволяют вам делать что -либо с потоком данных.
Связывание серии операторов может выполнить сложную логику. Код разбит на серию фрагментов, которые можно объединить. Это очарование программирования реактивной функции. Чем больше вы его используете, тем больше вы измените свое мышление программирования.
Кроме того, Rxjava также облегчает нам обработку данных. В последнем примере мы называем два API, обрабатывают данные, возвращаемые API, и сохраняем их на диск. Но наш подписчик этого не знает, он просто думает, что он получает наблюдаемый объект <string>. Хорошая упаковка также приносит удобство кодирования!
В третьей части я представлю некоторые другие классные функции rxjava, такие как обработка ошибок и параллелизм, которые не используются напрямую для обработки данных.