MVI DSL
March 2, 2022 · View on GitHub
Начало работы
Для того, чтобы начать работать с DSL, необходимо унаследовать Middleware, использующийся в проекте, от [DslFlowMiddleware], и переопределить метод transform(eventStream) следующим образом:
override fun transform(eventStream: Flow<SimpleEvent>): Flow<SimpleEvent> {
return eventStream.transformations {
// Здесь будут перечислены возможные трансформации
}
}
Добавление трансформаций
Для того, чтобы добавить эти трансформации, нужно вызвать либо метод addAll(vararg transformations: Flow<E>), либо унарный плюс: +Flow<T> для добавления по очереди.
Фильтрация по классу
Трансформации можно применять только к событиям определенных классов со следующим синтаксисом:
<Класс события> <тип трансформации> <трансформация>
Например, с помощью записи ниже, мы обновляем данные, как только получаем событие Reload:
Reload::class eventToStream { loadData() }
Типы трансформаций
Названия некоторых транформаций в новой версии отличаются. Решено было изменить названия, чтобы они были сходу понятны при чтении и вызывали меньше путаницы при использовании.
mapTo -> eventToEvent
eventMapTo -> eventToStream
streamMapTo -> streamToStream
- eventToEvent - трансформация события в событие. Используется, когда например событие клика по кнопке нужно трансформировать в событие открытие диалога.
В старой версии: mapTo
ButtonClicked::class eventToEvent { OpenSelectPhotoDialog() }
- eventToStream - трансформация события в поток событий. Полезно, например когда клик кнопки трансформируется в поток событий начала запроса к серверу, а когда ответ получен - в еще одно событие ошибки или успеха запроса. То есть получаем событие, а возвращаем поток событий.
В старой версии: eventMapTo
ReloadBtnClicked::class eventToStream {
interactor.loadData()
.asRequest(LoadDataEvent())
}
- streamToStream - трансформация потока событий в другой поток событий. Эта трансформация полезна, когда трансформации eventToEvent уже недостаточно и требуется модифицировать флоу событий, используя операторы реактивных цепочек. Например, filter, debounce, distinctUntilChanged и тд.
В старой версии: streamMapTo
TextChanged::class streamToStream { textChangedFlow ->
textChangedFlow
.map { it.text }
.filter { it.isNotEmpty() }
.debounce(300L, TimeUnit.MILLISECONDS)
.distinctUntilChanged()
.map { TextChangedDebounced(it) }
}
- react - когда нужно как-то отреагировать на событие, но не возвращать при этом никакого события в хаб. Например вызывать метод аналитики. То есть обратиться к чему-то, что при этом не потребует дальнейших обновлений состояния или трансформаций в другие события.
ButtonClicked::class react { event ->
analyticsService.sendEvent(TEXT_CHANGED, event.text)
}
- decompose (не поддерживается в текущей версии) - эта трансформация используется для обработки событий в другом Middleware. Например, на последних проектах в отдельный Middleware была вынесена логика обработки команд навигации, и на всех экранах, где требовалось совершать какие-то переходы в middleware, события навигации передавались для обработки в отдельный NavigationMiddleware.