Ответ 1
В Rx есть две части; Наблюдаемый паттерн и солидный набор операторов для манипулирования, преобразования и комбинирования их. Наблюдаемый паттерн сам по себе мало что делает. То же самое с сопрограммами; это просто еще одна парадигма, связанная с асинхронизмом. Вы можете сравнить плюсы и минусы обратных вызовов, Observable и сопрограмм для решения данной проблемы, но вы не можете сравнить парадигму с полнофункциональной библиотекой. Это как сравнивать язык с фреймворком.
Насколько сопрограммы Kotlin лучше, чем RxKotlin? Еще не использовал сопрограммы, но это похоже на async/wait в С#. Вы просто пишете последовательный код, все так же просто, как писать синхронный код... за исключением того, что он выполняется асинхронно. Это легче понять.
Зачем мне использовать сопрограммы kotlin? Я отвечу за себя. Большую часть времени я буду придерживаться Rx, потому что я предпочитаю управляемую событиями архитектуру. Но если возникнет ситуация, когда я пишу последовательный код и мне нужно вызывать асинхронный метод в середине, я с радостью использую сопрограммы, чтобы сохранить его таким образом и избегать оборачивания всего в Observable.
Редактировать: Теперь, когда я использую сопрограммы, пришло время для обновления.
RxKotlin - это просто синтаксический сахар для использования RxJava в Kotlin, поэтому я буду говорить о RxJava, а не о RxKotlin в следующем. Сопрограммы являются более низким рычагом и более общей концепцией, чем RxJava, они служат другим сценариям использования. Тем не менее, есть один вариант использования, где вы можете сравнить RxJava и сопрограммы (channel
), он передает данные асинхронно. Сопрограммы имеют явное преимущество перед RxJava здесь:
С сопрограммами лучше иметь дело с ресурсами
- В RxJava можно назначить вычисления для планировщиков, но
subscribeOn()
иObserveOn()
запутаны. Каждая сопрограмма получает контекст потока и возвращается в родительский контекст. Для канала обе стороны (производитель, потребитель) выполняют в своем собственном контексте. Сопрограммы более интуитивно понятны при воздействии на поток или пул потоков. - Сопрограммы дают больше контроля над тем, когда эти вычисления происходят. Например, вы можете передать hand (
yield
), расставить приоритеты (select
), распараллелить (несколькоproducer
/actor
наchannel
) или заблокировать ресурс (Mutex
) для данного вычисления. Это может не иметь значения на сервере (где RxJava пришел первым), но в среде с ограниченными ресурсами этот уровень контроля может потребоваться. - Из-за реактивного характера противодавление не очень хорошо в RxJava. С другой стороны,
send()
для канала - это функция приостановки, которая приостанавливается при достижении пропускной способности канала. Это нестандартное противодавление, данное природой. Вы также можетеoffer()
для канала, и в этом случае вызов никогда не приостанавливается, а возвращаетfalse
если канал заполнен, эффективно воспроизводяonBackpressureDrop()
из RxJava. Или вы можете просто написать свою собственную логику противодавления, что не составит труда с сопрограммами, особенно по сравнению с тем же с RxJava.
Есть еще один вариант использования, где сияют сопрограммы, и это ответит на ваш второй вопрос "Зачем мне использовать сопрограммы Kotlin?". Сопрограммы являются идеальной заменой фоновых потоков или AsyncTask
(Android). Это так же просто, как launch { someBlockingFunction() }
. Конечно, вы могли бы добиться этого и с RxJava, используя Schedulers
и Completable
возможно. Вы не будете (или мало) будете использовать шаблон Observer и операторы, которые являются сигнатурой RxJava, намек на то, что эта работа выходит за рамки RxJava. Сложность RxJava (бесполезный налог здесь) сделает ваш код более многословным и менее чистым, чем версия Coroutine.
Читаемость имеет значение. В этом отношении подходы RxJava и сопрограммы сильно различаются. Сопрограммы проще, чем RxJava. Если вам не очень flatmap()
с map()
, flatmap()
и функционально-реактивным программированием в целом, манипуляции с сопрограммами проще, включая базовые инструкции: for
, if
, try/catch
... Но лично я нахожу код сопрограммы труднее для понимания нетривиальные задачи. Особенно это связано с большим количеством вложений и отступов, в то время как цепочка операторов в RxJava поддерживает все в порядке. Функциональное программирование делает обработку более явной. Кроме того, RxJava может решать сложные преобразования с помощью нескольких стандартных операторов из их расширенного (ОК, слишком богатого) набора операторов. RxJava сияет, когда у вас сложные потоки данных, требующие большого количества комбинаций и преобразований.
Я надеюсь, что эти соображения помогут вам выбрать правильный инструмент с учетом ваших потребностей.