RxJava 2.0 — это расширение Java с открытым исходным кодом для асинхронного программирования от NetFlix. Оно гораздо ближе к функциональному программированию, как это видно в лямбда-выражениях Java 8. Основными строительными блоками реактивного кода являются Наблюдаемые и Подписчики. Наблюдаемый испускает элементы; Подписчик потребляет эти элементы.
RxJava также похож на шаблон проектирования Observer, но с одним отличием: Observables часто не начинают выдавать элементы, пока кто-то явно не подпишется на них.
1. Что такое RxJava и реактивное программирование
Реактивное программирование — это общий термин программирования, который фокусируется на реагировании на изменения, такие как значения данных или события. Обратный вызов — это подход к реактивному программированию, выполняемый императивно.
Например, если у вас есть один источник данных(производитель) и одна цель для данных(потребитель); то после подключения потребителя к подписчику – фреймворк реактивного программирования отвечает за передачу данных, сгенерированных производителем, потребителю. Обратите внимание, что наблюдаемый может иметь любое количество подписчиков.
Давайте рассмотрим очень простой пример RxJava Hello World.
package com.howtodoinjava.app;import io.reactivex.Observable;import io.reactivex.functions.Consumer;public class RxJava2Example{public static void main(String[] args){//producerObservable<String> observable = Observable.just("how", "to", "do", "in", "java");//consumerConsumer<? super String> consumer = System.out::println;//Attaching producer to consumerobservable.subscribe(consumer);}}
В приведенном выше примере «how», «to», «do», «in», «java» можно рассматривать как поток событий. Для этих событий создается наблюдаемый объект. Затем мы создаем потребителя, который может действовать на основе этих слов – в данном случае он просто выводит их на консоль. Этот потребитель – не что иное, как подписчик.
Наконец, мы подключаем подписчика к потребителю с помощью subscribe(). Как только мы подключаем обоих, слова/события начинают поступать, и подписчик начинает печатать их в консоли.
Внутри кода, когда новое слово выдается из наблюдаемого, метод onNext() вызывается для каждого подписчика. Когда наблюдаемый завершает все слова либо успешно, либо с ошибкой, для подписчика вызывается метод onComplete() или onError().
2. Зависимость RxJava 2
Чтобы включить RxJava 2.0 в среду выполнения вашего проекта, вы можете выбрать между заданной конфигурацией maven, конфигурацией gradle или файлом jar в classpath.
2.1 Зависимость RxJava 2.0 Maven
<!-- https://mvnrepository.com/artifact/io.reactivex.rxjava3/rxjava --><dependency><groupId>io.reactivex.rxjava2</groupId><artifactId>rxjava</artifactId><version>2.1.0</version></dependency>
2.2. Зависимость RxJava 2.0 Gradle
compile group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.1.0'
2.3 Зависимость Jar RxJava 2.0
Ссылка на скачивание Jar-файла RxJava 2.0.
3. Трансформация в RxJava
В RxJava тип события, который подписчик получает от наблюдаемого, и тип события, который подписчик испускает, не обязательно должны быть одинаковыми. Они могут отличаться по содержащимся в них данным, типам данных или любым другим существенным различиям между полученным и испущенным событием.
Это необходимо для обеспечения поддержки промежуточного преобразования событий между источником и целью, чтобы оба работали так, как они были спроектированы, и при этом были совместимы. Это очень похоже на шаблон проектирования адаптера.
Давайте рассмотрим пример. В нашем примере hello world мы хотим напечатать слова ЗАГЛАВНЫМИ БУКВАМИ. Это простое преобразование, но вы поймете концепцию.
Observable<String> observable = Observable.just("how", "to", "do", "in", "java");Consumer<? super String> consumer = System.out::println;//Transformation using map() methodobservable.map(w -> w.toUpperCase()).subscribe(consumer);
В примере выше мы добавили один промежуточный метод map() перед подпиской на наблюдаемый. Таким образом, каждое слово сначала проходит через метод map(), а затем отправляется подписчику для дальнейшей обработки. Это называется трансформацией.
Как упоминалось ранее, вы также можете изменить тип данных события в процессе преобразования, например:
Observable<String> observable = Observable.just("how", "to", "do", "in", "java");Consumer<? super Integer> consumer = System.out::println;observable.map(w -> w.toUpperCase().hashCode()).subscribe(consumer);
В этой программе мы перебираем слова, а затем в процессе преобразования получаем хэш-код слова и передаем его подписчику, который выводит хэш-код в консоль. Итак, здесь мы соединяем наблюдаемое, которое выдает строку, и подписчика, который принимает целое число.
4. Заключение
То, как observable и subscriber связаны свободно, дает разработчикам большое преимущество. Им не нужно думать о всей парадигме параллелизма, которая и так является сложной задачей для многих из нас. Вы просто соединяете производителя и подписчика – и все просто работает – безупречно.
Также вам не нужно думать о наблюдаемых и подписчиках одновременно. Вы можете разрабатывать их независимо с их лучшими дизайнерскими решениями, а затем соединять их с помощью концепции трансформации. Отлично!!
Этот учебник RxJava был скорее введением в RxJava. Я рассмотрю важные концепции, связанные с учебником реактивного программирования, более подробно в следующих учебниках rxjava для начинающих.