Как стать автором
Обновить

Комментарии 7

Спасибо за статью, как всегда очень основательно.

Вы не рассматривали возможность использовать мультибиндинги из какого-нибудь DI фреймворка или Manual DI? App ведь знает о всех модулях и может строить общий DI граф в котором может быть какая-то коллекция интерфейсов нужного типа.

Мультибиндинги рассматривали. Более того, до внедрения описанной в статье системы с meta-data, мультибиндинги были основным способом создания коллекций таких интерфейсов. Они и сейчас у нас остаются для, скажем так, не критичных штук - вроде диплинков и шорткатов.

В целом это весьма хорошее решение. Но конкретно у нас с таким подходом есть ряд проблем:

  • Нет прямой поддержки dynamic-feature, так как их код не виден из главного модуля.

  • Для демоприложений такой граф надо настраивать для каждого из демоприложений. Потом ещё и поддерживать. С системой с meta-data достаточно просто подключить модуль к приложению и он сам заработает.

  • У app есть два варианта "знать" о подключённых к нему модулях: implementation и runtimeOnly. Первый вариант позволяет видеть код из подключённых модулей в app, но в тоже время, если в каком-то из подключённых модулей меняется код, то и app вынужден пересобраться (иногда лишь частично, но не суть). Это било по времени горячей сборки и мы перешли на второй вариант - runtimeOnly. С ним код в app уже не доступен, зато и лишних пересборок нет. Так как код недоступен, то и от мультибиндингов смысла нет.

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

Есть ещё библиотека colonist от joom.

https://github.com/joomcode/colonist

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

Спасибо за статью, у меня 2 вопроса
1. почему бы вместо
private val receivers = mutableListOf<GlobalEventReceiver>()

взять SharedFlow ?
2. с многомодульной архитектурой все ивенты должны лежать в каком-то core модуле от которого должны зависить все остальные модули и каждый новый ивент влияет на сборку всех модулей. Как это победить ?

1) С ходу профита особого не вижу. Это просто property в которую идёт запись и чтение. Но если есть сценарий, где SharedFlow что-то сильно улучшит, то можно без проблем и его применить.

2) В таком случае можно GlobalEvent сделать не sealed class, а interface. Реализации хранить в нескольких модулях (например, api-модуль фичей), которые подключать к тем модулям, которым этот GlobalEvent нужен. Правда тут стоит быть аккуратным, если GlobalEvent нужен лишь ограниченному числу модулей, то возможно он не такой уж и глобальный? И стоит рассмотреть другие варианты общения между компонентами.

Спасибо за статью, весьма обширное количество примеров с минусами / плюсами / оптимизации.

У нас в приложении решили пойти немного другим путем, по доставке какого то события к какому то компоненту - это создание некого «почтового ящика», который позволяет записать событие условно в строку в БД и передать событие в интересующий модуль. Очень удобно и довольно не проблематично .

Зарегистрируйтесь на Хабре, чтобы оставить комментарий