Очередная навигация для Android Jetpack Compose? Brick

от автора

Я до последнего верил в Navigation component от google. Но, к сожалению, ряд задач с которыми я столкнулся при его использовании вместе с compose заставили поменять мое мнение. Идея создания собственного решения для навигации меня посещала часто, но я считал, что в этом нет необходимости. Ситуация вынудила меня!!! … и теперь я представляю — Brick.

Ну и зачем? В чем преимущество библиотеки?

Ну и сразу озвучу основную идею (и главное преимущество на мой взгляд), которую я преследовал — сделать максимально маленькое решение, которое позволит оторваться от фреймворка и строить проект как удобно. Да, отрыв от фреймворка. Например, тот же ViewModel. Штука хорошая, но проблем от нее тоже достаточно. Например, интеграция с Dagger. Ну это просто жесть, какие куски кода я видел по его интеграции. Кароче сложно, избыточно сложно.

Схема работы роутера
Схема работы роутера

В Brick же за рисование Compose отвечает отдельный компонент NavigationContainer и скормленный ему ContainerConnector. Поэтому сам Router может быть где угодно, и вызываться откуда угодно!

Ладно, и что там?

Основное понятие в Brick как я считаю — это Screen. Но это не просто Screen, который равен UI (как сразу может сложиться ассоциация). UI в Brick это часть Screen. Screen может существовать и без UI. Да, навигацию в Brick можно строить не строить от UI, а от бизнес логики. Да что это я, вы можете производить навигацию без UI! Но я не хотел этим ограничивать разработчиков. Поэтому, если вы хотите строить навигацию от UI, то это тоже можно реализовать.

Screen — имеет жизненный цикл. Не такой сложный как у Fragment, но все же он есть.
Всего два метода onCreate и onDestroy. Жизненным циклом управляет роутер.
В onCreate вы можете создать нужные зависимости и провести их в UI часть, там может быть ViewModel и прочее. Ну и собственно, Router и хранит всю эту информацию, поэтому важно, к какому ЖЦ вы привяжете сам роутер. Если это будет роутер привязанный к активити, то он будет жить пока живо активити. Если в application, то пока жив application.

Пример ЖЦ
Пример ЖЦ

Окей, не так уж и много, ради того чтобы использовать этот Brick. Еще есть что-то?

Здесь есть то, чего мне не хватало в Navigation от гугла.

1) Легче использовать, в четыре шага.

// 1 Создайте роутер val router: TreeRouter = TreeRouter.new() ...  // 2 Создайте Screen val screen1 = Screen<Unit>(   key = "1",   content = { SimpleScreen(1, "new") { smallSampleRouter.addScreen(screen2) } } // content - ui ) ...  // 3 Присоедините Container Connector (его реализует router) к NavigationContainer'у class SmallSampleActivity : ComponentActivity() {    val containerConnector: ContainerConnector = ... //inject or provide from application class    override fun onCreate(savedInstanceState: Bundle?) {       super.onCreate(savedInstanceState)        setContent {           ScreensContainer(containerConnector)       }   } }  // 4 Осуществляйте навигацию! router.addScreen(screen1)

2) Вложенная навигация, multibackstack, multibackstack внтури multibackstack и до бесконечной фантазии вашего разработчика UX.

Пример реализации
Пример реализации

Ну, а если схематично, то выглядит это вот так:

Справедливо заметить, что она есть и в Navigation Component. Но вы ее видели?) Или хотя бы использовали?) По моему мнению, она громоздка и неудобна в использовании.

3) Child навигация. Ее очень сильно не хватало, в Navigation Component. Конечно есть навигация в диалог и есть даже навигация в Bottom Sheet (правда в accompanist). Но она рушится, когда возникает задача сделать навигацию, где два Bottom Sheet один поверх другого и еще над ними Dialog.
Да, один над другим Bottom Sheet можно сделать использовав вложенность, но как быть, если логика внутри Bottom Sheet по объемам эквивалентна целому экрану? Вмещать три логики в один ViewModel? Разбивать ViewModel? А потом теряться в этих 500+ строчках кода или схемах связки, коммуникации между ViewModel? Слишком много вопросов и слишком рискованно, выбрав неверное решение можно потом увязнуть в трудно читаемом коде.

В Brick child навигация такая же как и screen и для условного UI компонента (диалога, bottom sheet) вы можете сделать свою сущность, где будете описывать логику, только для этого UI.

4) Передача аргументов. Вы видели ее в Navigation Component? Ну окей, там у них целая идея вокруг этого, вроде как ссылка и прочее, но мне кажется это неудобным. В Brick навигацию можно осуществлять с аргументами.
5) Общение между Screen. Почему нет? Сколько раз возникает задача общения между экранами? Да постоянно! Так вот, если вам это общение между Screen необходимо, то у каждого Screen есть flow, который принимает адресованные ему данные. И отправить их можно из любого Router’a независимо от того, вложенная у вас навигация или multiback stack

6) И еще множество мелких плюшек.

Хм, интересно…

Философия этой библиотеки заложена в ее названии. Brick — кирпич. И я хочу и постараюсь сделать так, чтобы Brick стал маленьким кирпичиком в структуре Android проекта. настолько маленьким, что его интеграция не составила большого труда в любой Android проект c Jetpack Compose.

Brick на GitHub


ссылка на оригинал статьи https://habr.com/ru/articles/594383/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *