Комментарии 16
Извините, но код корутин ужасен :/
Да и Rx-код тоже не подарок...
Вообще, все сравнение очень странное - каждый раз, когда RxJava предлагают, как фреймворк для асинхронного программирования, хочется выть. Это как гвозди микроскопом забивать.
У автора он не очень аккуратно написан. Можно лучше:
private suspend fun loadImages() {
withContext(Dispatchers.IO) {
loadEmails()
}
withContext(Dispatchers.Main) {
emailView.setAdapter(
ArrayAdapter(
applicationContext,
android.R.layout.simple_dropdown_item_1line,
getEmails()
)
)
}
}
К тому же эту функцию стоит сделать `suspend`, т.к. в реализации автора возможна утечка памяти
Можно еще немного "улучшить".
С большой долей вероятности, скоуп, в котором будет вызыватся эта функция уже будет построен на Main диспатчере (скоуп активити/фрагмента/вьюмодели). Соответсвенно, второе переключение контекста можно опустить.
Я бы не стал закладываться на такое предположение. Но можно сделать лучше, вместо `Dispatchers.Main` написать `Dispatchers.Main.immediate`. Так, если, поток уже Main, то переключения не произойдет
Насколько я знаю, предложенное greennick выше является хорошим тоном, во фрагментах и активити вызывать корутины именно на мэйн
Здесь дело не в коде, а в подходе, смысл статьи был показать что на корутинах код понятнее и читабельнее, код для статьи я писал на коленочке,
Минус Rx в том, что в нем довольно сложно разобраться так, чтобы писать аккуратный и понятный код. В вашем примере вы используете подход создания Observable, характерный для древней первой версии библиотеки. Сейчас это делается гораздо проще; более того, источники обычно создавать не нужно - Retrofit & Co давно умеют отдавать контракт Rx на выходе. К тому же, я так и не понял зачем в подписке создавать ArrayAdapter. Вы и про жизненный цикл не упомянули, и ваш пример будет утекать :\
Вот так мог бы выглядеть ваш код (жизненный цикл не завозил за неимением деталей использования примера):
abstract class Example {
fun pullEmails() {
Single.fromCallable { loadEmails() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::setViewItems)
}
abstract fun loadEmails(): List<String>
abstract fun setViewItems(items: List<String>)
}
Если же loadEmails ведет, например, в ретрофит, то даже fromCallable() не нужен
Но в реальных проектах все чаще вижу как раз неумелое использование Rx, где в subscribe вкорячивают лямбду на 200 строк и творят другую дичь. Просто сборник "как делать в Rx не надо"
Спасибо за комментарий, просто код для данной статьи я писал на коленке и над чистотой кода я не замолачивался, просто посыл данной стать был немного другой показать наглядно что при использовании корутин код становиться читабельнее и понятнее воспринимается на глаз
Не увидел преимуществ. Везде, где речь идет о Java vs Kotlin, единственным преимуществом называют красивый и читабельный код. А здесь пример еще более странной борьбы за красоту кода в пределах Kotlin.
Если программирую на Java, то у меня обычно нет проблем прочитать код.
Главный вопрос, который должен подниматься при сравнении разных подходов — что будет работать быстрее, и на сколько быстрее. Читабельность кода сегодня, мне кажется, не так критична. Должен быть баланс между читабельностью, скоростью разработки и скоростью работы итогового приложения.
А кто-нибудь понимает как сделать аналог Observable.amb (запуск нескольких операций паралельно, возврат результата только, как только сработает первая операция, остальные отменяются)?
Можно так https://arrow-kt.io/docs/fx/parallel/index.html#racing-parallel-operations, см раздел raceN. В kotlinx.coroutines пока нет из коробки, но есть issue https://github.com/Kotlin/kotlinx.coroutines/issues/2867. Напишите туда, зачем такая функция нужна. Может быстрее добавят)
С Handler'ом всё так. Про Rx не знал, но видимо и не нужно было. Корутины - интересно.
Handler vs RX vs Kotlin. Наглядный пример преимущества корутин