Combine vs flatMapLatest + map
По горячим следам вчерашнего собеса, осталось недопонимание в чем разница между этими операторами.
Для решения задачки действительно можно было бы использовать оба решения, но есть ли разница?
В случае использования flatMapLatest за место combine:
👉 Будем каждый раз при изменении токена, пересоздавать счетчик. Это не критично, но если переставить местами два flow, то будем уже каждый раз ходить в БД, и это уже плохо
👉 Если за место flatMapLatest использовать любой другой flatMap*, то получим некорректное поведение, так так не отменим ticker flow
👉 Так как flatMapLatest отменяет корутину, важно, чтобы ticker поддерживал кооперативную отмену, иначе снова получим некорректное поведение
Чтобы запомнить все разнообразие операторов и как они работают, очень советую интерактивные marble диаграммы. Этот сайт про RxJs, но на самом деле разницы особо нет, если вам каких-то операторов не хватает во Flow, то можно воспользоваться библиотекой FlowExt
#Coroutines
По горячим следам вчерашнего собеса, осталось недопонимание в чем разница между этими операторами.
Для решения задачки действительно можно было бы использовать оба решения, но есть ли разница?
В случае использования flatMapLatest за место combine:
👉 Будем каждый раз при изменении токена, пересоздавать счетчик. Это не критично, но если переставить местами два flow, то будем уже каждый раз ходить в БД, и это уже плохо
👉 Если за место flatMapLatest использовать любой другой flatMap*, то получим некорректное поведение, так так не отменим ticker flow
👉 Так как flatMapLatest отменяет корутину, важно, чтобы ticker поддерживал кооперативную отмену, иначе снова получим некорректное поведение
Чтобы запомнить все разнообразие операторов и как они работают, очень советую интерактивные marble диаграммы. Этот сайт про RxJs, но на самом деле разницы особо нет, если вам каких-то операторов не хватает во Flow, то можно воспользоваться библиотекой FlowExt
#Coroutines
Корутинные рецепты
Возможно вы уже видели набор полезных рецептов для Kotlin Coroutines от Marcin Moskala. Это набор утилитарных функций, которые помогают в повседневной разработке, позволяют значительно сократить код и сделать его лаконичнее.
🔹 Функция mapAsync позволяет элегантно сделать загрузку данных параллельной при работе с коллекциями
🔹 Функции retryWhen и retryBackoff позволяют сделать повторные запросы в случае ошибки, а вторая функция позволяет сделать ожидание экспоненциальным, чтобы увеличить вероятность успешного повтора
🔹 Функция raceOf позволяет запустить несколько suspend функций параллельно и получить результат той, что завершится быстрее остальных. На моей практике, это единственная функция, которая использует механизм select в корутинах.
🔹 Функция suspendLazy позволяет создать ленивое suspending свойство, которое не будет блочить поток, обращающийся к этому свойству
🔹 Ну и различные SharedDataSource и StateDataSource, которые нужны, чтобы пошарить один экземпляр Flow для нескольких подписчиков по переданному ключу.
📎 Помимо этих рецептов, также есть либа с полезными операторами для Flow, взятыми из Rx.
💡 Еще к этому списку можно было бы докинуть runCatchingCancellable, который не съедает CancellationException или функцию, противоположную raceOf, которая выберет самый медленный источник, ведь иногда нам нужно, наоборот, подзамедлить UI, чтобы он не мелькал и пользователь понимал, что происходит на экране.
Если вы знаете еще полезные экстеншены для корутин, делитесь ими в комментариях💬
#Coroutines
Возможно вы уже видели набор полезных рецептов для Kotlin Coroutines от Marcin Moskala. Это набор утилитарных функций, которые помогают в повседневной разработке, позволяют значительно сократить код и сделать его лаконичнее.
Если вы знаете еще полезные экстеншены для корутин, делитесь ими в комментариях
#Coroutines
Please open Telegram to view this post
VIEW IN TELEGRAM
Оператор RxJava, изменивший все
Недавно взялся за небольшой старый проект, в котором все еще большинство приложения было написано на RxJava, и я по всем правилам бойскаута переводил только новые куски на корутины до вчерашнего дня. Пока не пришлось столкнуться с огромной цепочкой, состоящей по меньшей мере из 15 операторов👋
Мне всего лишь нужно было добавить одно условие в оператор💁♂️
Тут новое поколение скажет: "Дед, ты таблетки забыл выпить, какая нафиг RxJava, какой еще Maybe"
В общем потупив минут 5, я решил, что оно того не стоит и переписал всю цепочку на корутины, а затем и весь проект... Иии... Результат того стоил!
👍 Все места, где использовались Single и Maybe стали обычными suspend функциями с последовательным кодом
👍 Эта сложная Rx цепочка вообще превратилась в цепочку котлиновских операторов над коллекцией
👍 Теперь нигде не нужно было явно переключать диспатчер
👍 А главное, что я переписал весь проект с первого раза, без единого бага 💪
👎 Без минусов, конечно, тоже не обошлось, в стандартной библиотеке Flow не всегда хватает операторов, например мне не хватило
Так что, подводя итог, я в очередной раз убедился, что несмотря на недостатки корутин, они значительно выигрывают у RxJava в плане читаемости и простоте кода, и нужно активно переходить на них в своих проектах, если вы еще этого не сделали, иначе скоро вы не сможете найти человека, который знает, что такое Maybe в RxJava.
💬 А в ваших проектах еще остался Rx?
#RxJava #Coroutines
@kotlin_adept
Недавно взялся за небольшой старый проект, в котором все еще большинство приложения было написано на RxJava, и я по всем правилам бойскаута переводил только новые куски на корутины до вчерашнего дня. Пока не пришлось столкнуться с огромной цепочкой, состоящей по меньшей мере из 15 операторов
Мне всего лишь нужно было добавить одно условие в оператор
onErrorResumeNext
, но то, как это делается с типом Single, абсолютно не подходит для типа Maybe, а казалось бы какая разница В общем потупив минут 5, я решил, что оно того не стоит и переписал всю цепочку на корутины, а затем и весь проект... Иии... Результат того стоил!
throttleFirst
и interval
, благо я знаю, где их искать и как написать самому, потому что с Flow кастомные операторы — это супер просто!Так что, подводя итог, я в очередной раз убедился, что несмотря на недостатки корутин, они значительно выигрывают у RxJava в плане читаемости и простоте кода, и нужно активно переходить на них в своих проектах, если вы еще этого не сделали, иначе скоро вы не сможете найти человека, который знает, что такое Maybe в RxJava.
#RxJava #Coroutines
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
Написал небольшую статью о рефакторинге архитектуры приложения с запутанной логикой.
По итогу получилось значительно упростить логику приложения и повысить надёжность. В этом помогли корутины, а точнее их не совсем стандартное применение.
Приятного чтения📖
#Architecture #Coroutines
@kotlin_adept
По итогу получилось значительно упростить логику приложения и повысить надёжность. В этом помогли корутины, а точнее их не совсем стандартное применение.
Приятного чтения
#Architecture #Coroutines
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegraph
Корутины — архитектурные помощники
Представьте, что у вас есть приложение, которое управляет пользовательскими данными. И вам пришла задача — отрефакторить подтверждение владения учётной записью для выполнения различных критически важных действий с аккаунтом пользователя. Таких действий может…
Интероп suspend и async функций
Ранее все suspend-функции в Kotlin превращались в обычные функции с completionHandler на стороне Swift, но начиная с Swift 5.5 появился интероп между корутинами в обе стороны. Однако пусть это не вводит вас в заблуждение: это всего лишь "сахар" в Swift, который преобразует коллбэки в асинхронные функции❗️
Соответственно, у вас будет работать базовый сценарий использования асинхронной функции, но на этом из хороших новостей всё:
❌ Запуск async-функции на Main-диспетчере не гарантирует выполнения на главном потоке в Swift.
❌ CancellationException не будет преобразовываться в CancellationError, соответственно, не будет работать кооперативная отмена корутин и есть риск получить work leak.
💡 Казалось бы, с этой проблемой может помочь библиотека SKIE, но и там не всё гладко. Она исправляет только интероп в одну сторону, когда мы вызываем suspend-функции из Swift-кода, но не в обратную.
Так что будьте осторожны с таким интеропом и следите за развитием полноценной поддержки в соответствующем issue.
#Coroutines #Kotlin #Swift
Ранее все suspend-функции в Kotlin превращались в обычные функции с completionHandler на стороне Swift, но начиная с Swift 5.5 появился интероп между корутинами в обе стороны. Однако пусть это не вводит вас в заблуждение: это всего лишь "сахар" в Swift, который преобразует коллбэки в асинхронные функции
Соответственно, у вас будет работать базовый сценарий использования асинхронной функции, но на этом из хороших новостей всё:
Так что будьте осторожны с таким интеропом и следите за развитием полноценной поддержки в соответствующем issue.
#Coroutines #Kotlin #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM