Rxjava-это реализация реактивных расширений Java VM: библиотека для составления асинхронных и на основе событий программ с использованием наблюдаемых последовательностей.
Он расширяет шаблон наблюдателя на поддержку последовательностей данных/событий и добавляет операторов, которые позволяют вам составлять последовательности вместе, декларативно, одновременно абстрагируя обеспокоенность по поводу таких вещей, как низкоуровневые потоки, синхронизация, безопасность потоков и одновременные структуры данных.
Узнайте больше о Rxjava в целом в вики -доме.
Пожалуйста, прочитайте то, что отличается в 3.0 для получения подробной информации об изменениях и миграции при обновлении с 2.x.
Версия 2.x-конец жизни по состоянию на 28 февраля 2021 года . Никакого дальнейшего развития, поддержки, технического обслуживания, PR и обновлений не произойдет. Javadoc самой последней версии, 2.2.21 , останется доступным.
Версия 1.x состоится в конце срока службы по состоянию на 31 марта 2018 года . Никакого дальнейшего развития, поддержки, технического обслуживания, PR и обновлений не произойдет. Javadoc самой последней версии, 1.3.8 , останется доступным.
Первый шаг - включить Rxjava 3 в ваш проект, например, в качестве зависимости Gradle Compil:
implementation " io.reactivex.rxjava3:rxjava:3.x.y "
(Пожалуйста, замените x
и y
на последние номера версий :)
Второе - написать программу Hello World :
package rxjava . examples ;
import io . reactivex . rxjava3 . core .*;
public class HelloWorld {
public static void main ( String [] args ) {
Flowable . just ( "Hello world" ). subscribe ( System . out :: println );
}
}
Обратите внимание, что компоненты Rxjava 3 сейчас живут под io.reactivex.rxjava3
, а базовые классы и интерфейсы живут под io.reactivex.rxjava3.core
.
Rxjava 3 включает в себя несколько базовых классов, на которых вы можете обнаружить операторов:
io.reactivex.rxjava3.core.Flowable
: 0..n потоки, поддерживающие реактивные потоки и обратное давлениеio.reactivex.rxjava3.core.Observable
: 0..n потоки, без обратного давления,io.reactivex.rxjava3.core.Single
: поток ровно 1 элемент или ошибка,io.reactivex.rxjava3.core.Completable
: поток без элементов, но только для завершения или сигнала ошибки,io.reactivex.rxjava3.core.Maybe
: поток без элементов, точно один элемент или ошибка.Заботы данных в rxjava состоят из источника, нуля или более промежуточных шагов, за которыми следуют потребитель данных или шаг комбинатора (где этап отвечает за потребление Dataflow каким -либо образом):
source . operator1 (). operator2 (). operator3 (). subscribe ( consumer );
source . flatMap ( value -> source . operator1 (). operator2 (). operator3 ());
Здесь, если мы представляем себя на operator2
, смотреть влево в сторону источника, называется восходящим по течению . Глядя вправо в сторону подписчика/потребителя, называется ниже по течению . Это часто более очевидно, когда каждый элемент написан на отдельной строке:
source
. operator1 ()
. operator2 ()
. operator3 ()
. subscribe ( consumer )
В документации Rxjava, выбросы , излучение , элемент , событие , сигнал , данные и сообщения считаются синонимами и представляют объект, движущийся вдоль потока данных.
Когда DATAFLOW проходит через асинхронные шаги, каждый шаг может выполнять разные вещи с разной скоростью. Чтобы избежать подавляющего такого шага, которые обычно проявляются в качестве увеличения использования памяти из-за временной буферизации или необходимости пропуска/сброса данных, применяется так называемое обратное давление, что является формой управления потоком, где шаги могут выразить, сколько элементов они готовы к обработке. Это позволяет ограничивать использование памяти потоков данных в ситуациях, когда, как правило, нет никакого способа узнать, сколько элементов будет отправлено вверх по течению.
В Rxjava выделенный Flowable
класс предназначен для поддержки обратного давления, а Observable
посвящено операциям, не связанным с перепрессавшим, (короткие последовательности, взаимодействия с графическим интерфейсом и т. Д.). Другие типы, Single
, Maybe
и Completable
не поддерживают обратное давление, и они не должны; Всегда есть место для временного хранения одного предмета.
Подготовка потоков данных путем применения различных промежуточных операторов происходит в так называемое время сборки :
Flowable < Integer > flow = Flowable . range ( 1 , 5 )
. map ( v -> v * v )
. filter ( v -> v % 3 == 0 )
;
На этом этапе данные еще не текут, и никаких побочных эффектов не происходит.
Это временное состояние, когда subscribe()
вызывается по потоку, который устанавливает цепочку этапов обработки внутри:
flow . subscribe ( System . out :: println )
Это когда запускаются побочные эффекты подписки (см. doOnSubscribe
). Некоторые источники блокируют или начинают излучать предметы сразу в этом состоянии.
Это состояние, когда потоки активно излучают предметы, ошибки или сигналы завершения:
Observable . create ( emitter -> {
while (! emitter . isDisposed ()) {
long time = System . currentTimeMillis ();
emitter . onNext ( time );
if ( time % 2 != 0 ) {
emitter . onError ( new IllegalStateException ( "Odd millisecond!" ));
break ;
}
}
})
. subscribe ( System . out :: println , Throwable :: printStackTrace );
Практически, это когда тело приведенного выше примера выполняет.
Одним из общих вариантов использования Rxjava является запуск некоторых вычислений, сетевого запроса на фоновом потоке и показать результаты (или ошибку) в потоке пользовательского интерфейса:
import io . reactivex . rxjava3 . schedulers . Schedulers ;
Flowable . fromCallable (() -> {
Thread . sleep ( 1000 ); // imitate expensive computation
return "Done" ;
})
. subscribeOn ( Schedulers . io ())
. observeOn ( Schedulers . single ())
. subscribe ( System . out :: println , Throwable :: printStackTrace );
Thread . sleep ( 2000 ); // <--- wait for the flow to finish
Этот стиль методов цепочки называется беглым API , который напоминает паттерн строителя . Тем не менее, реактивные типы Rxjava неизменны; Каждый из вызовов метода возвращает новый Flowable
с добавленным поведением. Чтобы проиллюстрировать, пример можно переписан следующим образом:
Flowable < String > source = Flowable . fromCallable (() -> {
Thread . sleep ( 1000 ); // imitate expensive computation
return "Done" ;
});
Flowable < String > runBackground = source . subscribeOn ( Schedulers . io ());
Flowable < String > showForeground = runBackground . observeOn ( Schedulers . single ());
showForeground . subscribe ( System . out :: println , Throwable :: printStackTrace );
Thread . sleep ( 2000 );
Как правило, вы можете перемещать вычисления или блокировать io в какой -то другой поток через subscribeOn
. После того, как данные будут готовы, вы можете убедиться, что они обрабатываются на переднем плане или потоке графического интерфейса через observeOn
.
Операторы Rxjava не работают с Thread
S или ExecutorService
напрямую, но с так называемым Scheduler
, которые абстрагируют источники параллелизма, стоящую за единым API. Rxjava 3 имеет несколько стандартных планировщиков, доступных через класс утилиты Schedulers
.
Schedulers.computation()
: запустить интенсивную работу по вычислению на фиксированном количестве выделенных потоков в фоновом режиме. Большинство асинхронных операторов используют это в качестве Scheduler
по умолчанию.Schedulers.io()
: запустить операции ввода-вывода или блокировки на динамически изменяющемся наборе потоков.Schedulers.single()
: запустить работу по одному потоку в последовательном и FIFO.Schedulers.trampoline()
: запустить работу в последовательном и FIFO манера в одной из участвующих потоков, обычно для целей тестирования. Они доступны на всех платформах JVM, но некоторые конкретные платформы, такие как Android, имеют свой собственный типичный Scheduler
: AndroidSchedulers.mainThread()
, SwingScheduler.instance()
или JavaFXScheduler.platform()
.
Кроме того, есть возможность завершить существующего Executor
(и его подтипы, такие как ExecutorService
) в Scheduler
через Schedulers.from(Executor)
. Например, это можно использовать для того, чтобы иметь более крупный, но все еще фиксированный пул потоков (в отличие от computation()
и io()
соответственно).
Thread.sleep(2000);
В конце не случайно. В rxjava Scheduler
по умолчанию запускается на потоках демона, что означает, что после выхода основного потока Java все они останавливаются, и фоновые вычисления могут никогда не произойти. Сон в течение некоторого времени в этом примере ситуаций позволяет вам увидеть вывод потока на консоли со временем.
Потоки в rxjava имеют последовательные по своей природе, разделенные на стадии обработки, которые могут работать одновременно друг с другом:
Flowable . range ( 1 , 10 )
. observeOn ( Schedulers . computation ())
. map ( v -> v * v )
. blockingSubscribe ( System . out :: println );
В этом примере проторивает числа от 1 до 10 в Scheduler
вычислений и потребляет результаты в «основном» потоке (точнее, поток вызывающего абонента blockingSubscribe
). Тем не менее, лямбда v -> v * v
не работает параллельно для этого потока; Он получает значения от 1 до 10 в одном и том же вычислительном потоке один за другим.
Обработка чисел от 1 до 10 параллельно немного больше:
Flowable . range ( 1 , 10 )
. flatMap ( v ->
Flowable . just ( v )
. subscribeOn ( Schedulers . computation ())
. map ( w -> w * w )
)
. blockingSubscribe ( System . out :: println );
Практически параллелизм в rxjava означает запуск независимых потоков и объединение их результатов в один поток. Оператор flatMap
делает это первым отображением каждого числа с 1 до 10 в свой собственный индивидуальный Flowable
, запускает их и объединяет вычисленные квадраты.
Обратите внимание, однако, что flatMap
не гарантирует какой -либо заказ, и элементы из внутренних потоков могут в конечном итоге переоценены. Есть альтернативные операторы:
concatMap
, который отображает и запускает по одному внутреннему потоку за раз иconcatMapEager
, который запускает все внутренние потоки сразу «но выходной поток будет в том порядке, созданный эти внутренние потоки. В качестве альтернативы оператор Flowable.parallel()
и ParallelFlowable
тип помогают достичь такой же параллельной обработки:
Flowable . range ( 1 , 10 )
. parallel ()
. runOn ( Schedulers . computation ())
. map ( v -> v * v )
. sequential ()
. blockingSubscribe ( System . out :: println );
flatMap
является мощным оператором и помогает во многих ситуациях. Например, учитывая услугу, которая возвращает Flowable
, мы хотели бы вызвать другую службу со значениями, излучаемыми первой службой:
Flowable < Inventory > inventorySource = warehouse . getInventoryAsync ();
inventorySource
. flatMap ( inventoryItem -> erp . getDemandAsync ( inventoryItem . getId ())
. map ( demand -> "Item " + inventoryItem . getName () + " has demand " + demand ))
. subscribe ( System . out :: println );
Иногда, когда элемент стал доступен, хотелось бы выполнить некоторые зависимые вычисления на нем. Иногда это называется продолжением , и, в зависимости от того, что должно произойти и какие типы задействованы, могут привлечь различные операторы для достижения.
Наиболее типичный сценарий - дать ценность, вызовать другую услугу, ожидание и продолжение с его результатом:
service . apiCall ()
. flatMap ( value -> service . anotherApiCall ( value ))
. flatMap ( next -> service . finalCall ( next ))
Часто относится также к тому, что более поздние последовательности потребуют значений из более ранних сопоставлений. Это может быть достигнуто путем перемещения внешней flatMap
в внутренние части предыдущей flatMap
, например:
service . apiCall ()
. flatMap ( value ->
service . anotherApiCall ( value )
. flatMap ( next -> service . finalCallBoth ( value , next ))
)
Здесь исходное value
будет доступно внутри внутренней flatMap
, любезно предоставленного переменным захватом Lambda.
В других сценариях результат (ы) первого источника/потока данных не имеет значения, и кто -то хотел бы продолжить с квази -независимым другим источником. Здесь flatMap
также работает:
Observable continued = sourceObservable . flatMapSingle ( ignored -> someSingleSource )
continued . map ( v -> v . toString ())
. subscribe ( System . out :: println , Throwable :: printStackTrace );
Тем не менее, продолжение в этом случае остается Observable
вместо вероятного более подходящего Single
. (Это понятно, потому что с точки зрения flatMapSingle
, sourceObservable
является многозначным источником, и, следовательно, отображение также может привести к нескольким значениям).
Часто, хотя существует способ, который является несколько более выразительным (а также ниже), используя Completable
в качестве посредника и его оператора andThen
возобновить что -то еще:
sourceObservable
. ignoreElements () // returns Completable
. andThen ( someSingleSource )
. map ( v -> v . toString ())
Единственная зависимость между sourceObservable
и someSingleSource
заключается в том, что первое должно нормально завершать, чтобы последнее было употребляется.
Иногда между предыдущей последовательности и новой последовательности существует неявная зависимость данных, которая по какой -то причине не проходила через «обычные каналы». Можно было бы написать такие продолжения следующим образом:
AtomicInteger count = new AtomicInteger ();
Observable . range ( 1 , 10 )
. doOnNext ( ignored -> count . incrementAndGet ())
. ignoreElements ()
. andThen ( Single . just ( count . get ()))
. subscribe ( System . out :: println );
К сожалению, это печатает 0
, потому что Single.just(count.get())
оценивается во время сборки, когда Dataflow еще даже не запускается. Нам нужно что -то, что определяет оценку этого Single
источника до среды выполнения , когда основной источник завершится:
AtomicInteger count = new AtomicInteger ();
Observable . range ( 1 , 10 )
. doOnNext ( ignored -> count . incrementAndGet ())
. ignoreElements ()
. andThen ( Single . defer (() -> Single . just ( count . get ())))
. subscribe ( System . out :: println );
или
AtomicInteger count = new AtomicInteger ();
Observable . range ( 1 , 10 )
. doOnNext ( ignored -> count . incrementAndGet ())
. ignoreElements ()
. andThen ( Single . fromCallable (() -> count . get ()))
. subscribe ( System . out :: println );
Иногда источник или служба возвращает другой тип, чем поток, который должен работать с ним. Например, в примере инвентаризации выше, getDemandAsync
может вернуть Single<DemandRecord>
. Если пример кода остается неизменным, это приведет к ошибке времени компиляции (однако, часто с вводящим в заблуждение сообщением об ошибке об отсутствии перегрузки).
В таких ситуациях обычно существует два варианта исправления преобразования: 1) преобразовать в желаемый тип или 2) найти и использовать перегрузку конкретного оператора, поддерживающего различный тип.
Каждый реактивный базовый класс имеет операторы, которые могут выполнять такие преобразования, включая преобразования протокола, чтобы соответствовать некоторым другим типам. На следующей матрице показаны доступные параметры преобразования:
Протекаемый | Наблюдаемый | Одинокий | Может быть | Завершается | |
---|---|---|---|---|---|
Протекаемый | toObservable | first , firstOrError , single , singleOrError , last , lastOrError 1 | firstElement , singleElement , lastElement | ignoreElements | |
Наблюдаемый | toFlowable 2 | first , firstOrError , single , singleOrError , last , lastOrError 1 | firstElement , singleElement , lastElement | ignoreElements | |
Одинокий | toFlowable 3 | toObservable | toMaybe | ignoreElement | |
Может быть | toFlowable 3 | toObservable | toSingle | ignoreElement | |
Завершается | toFlowable | toObservable | toSingle | toMaybe |
1 : При превращении многозначного источника в однозначный источник следует решить, какое из многих источников следует рассматривать как результат.
2 : Превращение Observable
в Flowable
требует дополнительного решения: что делать с потенциальным неограниченным потоком источника, Observable
? Существует несколько доступных стратегий (таких как буферизация, сброс, сохранение последних) через параметр BackpressureStrategy
или через стандартные Flowable
операторы, такие как onBackpressureBuffer
, onBackpressureDrop
, onBackpressureLatest
который также позволяет дальнейшей настройке поведения обратного давления.
3 : Когда есть только (максимум) один из источников, нет проблем с обратным давлением, поскольку его всегда можно хранить, пока нижний поток не будет готов к потреблению.
Многие часто используемые операторы имеют перегрузки, которые могут иметь дело с другими типами. Они обычно называют суффиксом целевого типа:
Оператор | Перегрузки |
---|---|
flatMap | flatMapSingle , flatMapMaybe , flatMapCompletable , flatMapIterable |
concatMap | concatMapSingle , concatMapMaybe , concatMapCompletable , concatMapIterable |
switchMap | switchMapSingle , switchMapMaybe , switchMapCompletable |
Причина, по которой эти операторы имеют суффикс вместо того, чтобы просто иметь одинаковое имя с различной подписью, - это стирание типа. Java не рассматривает подписи, такие как operator(Function<T, Single<R>>)
и operator(Function<T, Maybe<R>>)
отличается (в отличие от C#) и из -за стирания, два operator
в итоге в конечном итоге как дубликаты методов с той же подписью.
Наименование в программировании - одна из самых сложных вещей, поскольку имена, как ожидается, не будут длинными, выразительными, захватывающими и легко запоминающимися. К сожалению, целевой язык (и ранее существовавшие соглашения) не может оказать слишком большую помощь в этом отношении (непригодные ключевые слова, стирание типа, неоднозначности типа и т. Д.).
В исходном rx.net оператор, который издает один элемент, а затем завершается, называется Return(T)
. Поскольку конвенция Java состоит в том, чтобы запустить строчную букву название метода, это было бы return(T)
которое является ключевым словом в Java и, следовательно, недоступно. Поэтому Rxjava решил назвать этого оператора just(T)
. Такое же ограничение существует для Switch
, который должен был быть назван switchOnNext
. Еще одним примером является Catch
, которое было названо onErrorResumeNext
.
Многие операторы, которые ожидают, что пользователь предоставит некоторую функцию, возвращающую реактивный тип, не могут быть перегружены, потому что стирание типа вокруг Function<T, X>
превращает такие подписи метода в дубликаты. Rxjava решил назвать таких операторов, добавив тип в качестве суффикса:
Flowable < R > flatMap ( Function <? super T , ? extends Publisher <? extends R >> mapper )
Flowable < R > flatMapMaybe ( Function <? super T , ? extends MaybeSource <? extends R >> mapper )
Несмотря на то, что у некоторых операторов нет проблем с стиранием типа, их подпись может оказаться неоднозначной, особенно если кто -то использует Java 8 и Lambdas. Например, существует несколько перегрузки concatWith
, принимающих различные другие типы реактивных баз в качестве аргументов (для предоставления удобства и преимуществ производительности в базовой реализации):
Flowable < T > concatWith ( Publisher <? extends T > other );
Flowable < T > concatWith ( SingleSource <? extends T > other );
И Publisher
, и SingleSource
появляются как функциональные интерфейсы (типы с одним абстрактным методом) и могут побудить пользователей попытаться предоставить Lambda выражение:
someSource . concatWith ( s -> Single . just ( 2 ))
. subscribe ( System . out :: println , Throwable :: printStackTrace );
К сожалению, этот подход не работает, и пример вообще не печатает 2
. Фактически, с версии 2.1.10, она даже не компилируется, потому что существует не менее 4 перегрузки concatWith
, и компилятор находит код выше двусмысленного.
Пользователь в таких ситуациях, вероятно, хотел отложить некоторые вычисления до someSource
пор, пока не будет завершен, поэтому правильный однозначный оператор должен был быть defer
:
someSource . concatWith ( Single . defer (() -> Single . just ( 2 )))
. subscribe ( System . out :: println , Throwable :: printStackTrace );
Иногда добавляется суффикс, чтобы избежать логических неясностей, которые могут составлять, но создавать неправильный тип в потоке:
Flowable < T > merge ( Publisher <? extends Publisher <? extends T >> sources );
Flowable < T > mergeArray ( Publisher <? extends T >... sources );
Это также может стать неоднозначным, когда функциональные типы интерфейса участвуют в качестве аргумента типа T
.
DataFlows могут не сработать, после чего ошибка испускается потребителю (ов). Иногда, однако, несколько источников могут потерпеть неудачу, после чего есть выбор, независимо от того, дождаться или нет, пока все они завершит или потерпят неудачу. Чтобы указать эту возможность, многие имена операторов суффиксуют словами DelayError
(в то время как другие имеют логический флаг delayError
или delayErrors
с логическим флагом в одной из их перегрузки):
Flowable < T > concat ( Publisher <? extends Publisher <? extends T >> sources );
Flowable < T > concatDelayError ( Publisher <? extends Publisher <? extends T >> sources );
Конечно, суффиксы различных видов могут появиться вместе:
Flowable < T > concatArrayEagerDelayError ( Publisher <? extends T >... sources );
Базовые классы можно считать тяжелыми из -за огромного количества методов статического и экземпляра. На дизайн Rxjava 3 сильно повлияла спецификация реактивных потоков, поэтому библиотека имеет класс и интерфейс на каждый реактивный тип:
Тип | Сорт | Интерфейс | Потребитель |
---|---|---|---|
0..n обратно | Flowable | Publisher 1 | Subscriber |
0..n безгранично | Observable | ObservableSource 2 | Observer |
1 элемент или ошибка | Single | SingleSource | SingleObserver |
0..1 элемент или ошибка | Maybe | MaybeSource | MaybeObserver |
0 элемент или ошибка | Completable | CompletableSource | CompletableObserver |
1 org.reactivestreams.Publisher
является частью библиотеки внешних реактивных потоков. Это основной тип взаимодействия с другими реактивными библиотеками с помощью стандартизированного механизма, управляемого спецификацией реактивных потоков.
2 Конвенция об именах интерфейса состояла в том, чтобы добавить Source
к полу-традиционному имени класса. Не существует FlowableSource
, так как Publisher
предоставляется библиотекой реактивных потоков (и подтинг, это также не помогло бы с взаимодействием). Эти интерфейсы, однако, не являются стандартными в смысле спецификации реактивных потоков и в настоящее время являются только Rxjava.
По умолчанию сама Rxjava не требует каких -либо настроек Proguard/R8 и должен работать без проблем. К сожалению, зависимость реактивных потоков с момента версии 1.0.3 внедряет файлы класса Java 9 в свою банку, которые могут вызвать предупреждения с простой прогикой:
Warning: org.reactivestreams.FlowAdapters$FlowPublisherFromReactive: can't find superclass or interface java.util.concurrent.Flow$Publisher
Warning: org.reactivestreams.FlowAdapters$FlowToReactiveProcessor: can't find superclass or interface java.util.concurrent.Flow$Processor
Warning: org.reactivestreams.FlowAdapters$FlowToReactiveSubscriber: can't find superclass or interface java.util.concurrent.Flow$Subscriber
Warning: org.reactivestreams.FlowAdapters$FlowToReactiveSubscription: can't find superclass or interface java.util.concurrent.Flow$Subscription
Warning: org.reactivestreams.FlowAdapters: can't find referenced class java.util.concurrent.Flow$Publisher
Рекомендуется, чтобы он установил следующую запись -dontwarn
в файле proguard-ruleset
для приложения:
-dontwarn java.util.concurrent.Flow*
Для R8 rxjava jar включает в себя META-INF/proguard/rxjava3.pro
с одинаковым предложением без ворота и должна применяться автоматически.
Для получения дополнительной информации проконсультируйтесь с вики.
Версия 3.x находится в разработке. Ошибки на ошибках будут применены как к филиалам 2.x, так и к 3.x, но новые функции будут добавлены только в 3.x.
Незначительные приращения 3.x (такие как 3,1, 3.2 и т. Д.) произойдут, когда будут добавлены новая нетривиальная функциональность, или возникают значительные улучшения или исправления ошибок, которые могут иметь поведенческие изменения, которые могут повлиять на некоторые краевые случаи (такие как зависимость от поведения, возникающие в результате ошибка). Примером улучшения, которое будет классифицировать, поскольку это добавляет поддержку обратного дальности к оператору, который ранее не поддерживал его. Это должно быть обратно совместимым, но ведет себя по -разному.
Приращения патча 3.xy (например, 3.0.0 -> 3.0.1, 3.3.1 -> 3.3.2, и т. Д.) Для исправлений ошибок и тривиальной функциональности (например, добавление метода перегрузки). Новая функциональность, отмеченная @Beta
или @Experimental
Annotation, также может быть добавлена в выбросы патчей, чтобы обеспечить быстрое исследование и итерацию нестабильной новой функции.
API, отмеченные аннотацией @Beta
на уровне класса или метода, могут быть изменены. Они могут быть изменены каким -либо образом или даже удалены в любое время. Если ваш код является самой библиотекой (то есть он используется на группе пользователей вне вашего контроля), вы не должны использовать бета -API, если вы не переупаковываете их (например, используя прогирду, затенение и т. Д.).
API, отмеченные @Experimental
Annotation на уровне класса или метода, почти наверняка изменится. Они могут быть изменены каким -либо образом или даже удалены в любое время. Вы не должны использовать или полагаться на них в любом производственном коде. Они являются исключительно, чтобы обеспечить широкое тестирование и обратную связь.
API, помеченные @Deprecated
Annotation на уровне класса или метода, останутся поддержанным до следующего крупного выпуска, но рекомендуется прекратить их использование.
Весь код внутри io.reactivex.rxjava3.internal.*
Пакеты считаются частными API и не следует полагаться вообще. Это может измениться в любое время.
http://reactivex.io/RxJava/3.x/javadoc/3.xy/
Информация о двоичных файлах и зависимости для Maven, Ivy, Gradle и других можно найти по адресу http://search.maven.org.
Пример для Gradle:
implementation ' io.reactivex.rxjava3:rxjava:x.y.z '
и для Maven:
< dependency >
< groupId >io.reactivex.rxjava3</ groupId >
< artifactId >rxjava</ artifactId >
< version >x.y.z</ version >
</ dependency >
и для Айви:
< dependency org = " io.reactivex.rxjava3 " name = " rxjava " rev = " x.y.z " />
Снимки после 1 мая 2021 года доступны через https://oss.sonatype.org/content/repositories/snapshots/io/reactivex/rxjava3/rxjava/
repositories {
maven { url ' https://oss.sonatype.org/content/repositories/snapshots ' }
}
dependencies {
implementation ' io.reactivex.rxjava3:rxjava:3.0.0-SNAPSHOT '
}
Снимки Javadoc доступны по адресу http://reactivex.io/rxjava/3.x/javadoc/snapshot
Построить:
$ git clone [email protected]:ReactiveX/RxJava.git
$ cd RxJava/
$ ./gradlew build
Более подробную информацию о строительстве можно найти на странице начала работы вики.
Для ошибок, вопросов и обсуждений, пожалуйста, используйте проблемы GitHub.
Copyright (c) 2016-present, RxJava Contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.