Skip to content

ruslansharipov/mvi-flow

Repository files navigation

Что это?

Современная библиотека для организации слоя представления, следующая идеалогии UDF.
Является продолжением и развитием идей библиотеки Surf-MVI

mvi-core

Основная идея в том, что у экрана есть единое состояние.
Логика изменения этого состояния отделена от логики запросов в сеть или базу данных. Все, что происходит на экране это события. Ответственность за изменение состояния лежит строго на отдельной сущности - reducer’е. То есть изменять состояние экрана не может никто, кроме reducer’а.
Ответственность за трансформацию событий лежит на middleware.

Таким образом вся логика, приводящая к изменению состояния UI концентрируется в одном месте и она отделена от логики запросов к серверу, в базу данных, получению каких-то обновлений с других экранов итд. А вью остается только отрисовывать это состояние и отправлять события взаимодействия с пользователем.

mvi-flow

В 2020 стэк android отдела был полностью завязан на RxJava и все проекты, стартовавшие в студии использовали MVI для организации слоя представления. И библиотека, которая для этого использовалась была полностью основана на реактивных потоках, реализованных с помощью RxJava.

В 2021 году стартовало обновление стэка android отдела. И в будущем планируется уйти полностью от RxJava и в новых проектах использовать корутины и Flow. Но от MVI отказываться не хотелось, поэтому я перенес идеи, которые были заложены и реализованы в библиотеке mvi-surf в библиотеку mvi-flow. Сущности и их ответственности остались все те же самые.

  1. Reducer - получает на вход событие и на основе этого события возвращает новое состояние (или старое, если событие не требует изменения состояния UI).
  2. Middleware - трансформирует потоки событий. Например событие клика по кнопке в событие начала сетевого запроса.
  3. View - подписывается на изменения состояния и изменяется в соответствие с ними.
  4. EventHub - основная и единственная шина событий, происходящих на экране.
  5. ScreenBinder - объединяет все сущности для совместной работы. Подписывает Middleware на события экрана для их трансформации, трансформированные события отправляет в EventHub, а также уведомляет редьюсер о каждом новом событии и хабе.

DSL

Одной из главных фишек библиотеки Surf-MVI был DSL, позволяющий описывать трансформации событий в лаконичном стиле используя средства котлина.
mvi-flow уже подерживает почти все DSL-трансформации к которым мы уже привыкли

  1. map - трансформация события в событие
  2. eventMap - трансформация события в поток событий
  3. streamMap - трансформация потока событий в поток событий
  4. react - простая реакция на событие

//TODO

  • декомпозиция событий
  • фильтрация событий в DSL

Зачем так усложнять?

В эпоху, когда все писали приложения используя MVP и выполняя команды на вью меняя его состояние очень легко было попасть в ситуацию, когда какой-то блок кода приводит вью в состояние, которое не соответствует ожидаемому.
На простых экранах это редко происходило, но чем сложнее становилась логика презентера - тем чаще начинали возникать эти ситуации.
Например обычным делом было вынести отдельно команды отображения и скрытия загрузчика на вью. И в начале выполнения какого-то запроса выполнять команду отображения, а при завершении запроса выполнять команду скрытия. Но что если на экране несколько запросов? А что если какой-то из них завершается с ошибкой? Или один завершится быстрее другого? Или есть один из них начнет выполнение позже другого? В каком порядке выполнятся эти команды?

Аналогично реализации MVVM, рекомендованной гуглом, когда у вьюмодели есть несколько Observable полей по типу isLoading: StateFlow, isError: StateFlow.
А сама вьюмодель при этом во время работы экрана меняет флаги в этих состояниях.

Чем сложнее становится логика экранов тем сложнее поддерживать консистентное состояние вью вызывая на ней нужные команды в случае MVP (часто важен даже порядок их вызова) или изменяя несколько Observable состояний.

Отделение логики изменения вью от бизнес-логики позволяет создавать очень сложные экраны. При этом не приходится работать с огромным презентером на несколько тысяч строк, который содержит большое количество логики и чем сложнее эта логика - тем более хрупким становится код в нем.

Пример

Реализацию простого экрана с полным набором сущностей и классов можно посмотреть в модуле sample

Если у вас есть мысли которые помогут развить идеи этой библиотеки

Telegram: @RuslanSharipov
Gmail: [email protected]

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages