Size: a a a

Android Architecture

2020 May 27

D

Dmitriy in Android Architecture
Mikhail Mustakimov
Звучит, если честно, костыльно)
просто представьте, что через месяц (внезапно) в апи добавят поле в объект, которое должно содержать (например) AdvertisingId
оно не является частью бизнес-логики, просто беку нужно для чего-то

в этом случае вы поправите только код слоя "API", а не устроите рефакторинг с правкой объектов/импортов по всем слоям
источник

АЕ

Алексей Ершов... in Android Architecture
Mikhail Mustakimov
Кстати, в ней нет ссылки на чат GitFox
описание чата немножечко застряло. Исправим)
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
Какими? Между пердок-ребёнок или между двумя разными детьми?
в любом варианте. Вот у вас есть фрагмент Ф1 и фрагмент Ф2 на активити А. Есть колбэк интерфейс, который предоставляется фрагменту Ф2 фрагментом Ф1 (худший вариант) или от активити (немного лучше)
В первом случае, Ф1 зависит от Ф2 - если Ф2 вдруг исчез, Ф1 при попытке дернуть колбэк обвалится. Если есть еще один фрагмент Ф3, реагирущий на Ф1, нужно будет делать либо еще один колбэк, либо менять существующий. Если Ф1 вдруг хочет передать не только id, но и скажем какой-то фильтр, придется менять колбэк. Ну и тогдалие
источник

AI

Arkadii Ivanov in Android Architecture
Dm Savin
в любом варианте. Вот у вас есть фрагмент Ф1 и фрагмент Ф2 на активити А. Есть колбэк интерфейс, который предоставляется фрагменту Ф2 фрагментом Ф1 (худший вариант) или от активити (немного лучше)
В первом случае, Ф1 зависит от Ф2 - если Ф2 вдруг исчез, Ф1 при попытке дернуть колбэк обвалится. Если есть еще один фрагмент Ф3, реагирущий на Ф1, нужно будет делать либо еще один колбэк, либо менять существующий. Если Ф1 вдруг хочет передать не только id, но и скажем какой-то фильтр, придется менять колбэк. Ну и тогдалие
Пожалуйста, посмотрите на этот пример: https://gist.github.com/arkivanov/dd1e8081aa1356a98c9603be95b4aa09
ListFragment и DetailsFragment знают только каждый о себе. RootFragment знает только о ListFragment и DetailsFragment. Переиспользовать любой фрагмент легко, достаточно удовлетворить его зависимости. Также есть безопасность при сборке: если добавится новый Output или изменятся зависимости - проект перестанет собираться.
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
Пожалуйста, посмотрите на этот пример: https://gist.github.com/arkivanov/dd1e8081aa1356a98c9603be95b4aa09
ListFragment и DetailsFragment знают только каждый о себе. RootFragment знает только о ListFragment и DetailsFragment. Переиспользовать любой фрагмент легко, достаточно удовлетворить его зависимости. Также есть безопасность при сборке: если добавится новый Output или изменятся зависимости - проект перестанет собираться.
Я, к сожалению, совсем не умею в gist, и не очень понял логику создания фрагментов.
Вот мой пример (не очень хороший, но имхо выражащий позицию) - https://github.com/lcch0/tests/tree/master/test1/src
источник
2020 May 28

AI

Arkadii Ivanov in Android Architecture
Dm Savin
Я, к сожалению, совсем не умею в gist, и не очень понял логику создания фрагментов.
Вот мой пример (не очень хороший, но имхо выражащий позицию) - https://github.com/lcch0/tests/tree/master/test1/src
Вот несколько комментариев по вашему коду:
1. Дочерние фрагменты связаны общим классом Model - это как раз и есть связность. В предолженном мной варианте, дочерние фрагменты совершенно независимы и могу находится в разных модулях.
2. У Вас ListFragment умеет только сообщать о том, что выбран элемент. Ему не надо надо уметь читать listId из ListViewModel. Это нарушение I из SOLID.
3. Из пункта 2 вытекает то же самое для ListViewModel - она может только писать в Model. Опять нарушается I из SOLID - чтение должно быть недоступно.
4. Тоже самое для DetailsViewModel, ей не нужно уметь изменять listId
5. DetailsViewModel подписывается на Model, но не отписывается. Т.к. жизненный цикл Model потенциально может быть шире, можно получить утечку.
6. DetailsFragment не отписывается от DetailsViewModel - может быть утечка
7. Оба фрагемента сразу добавляются в иерархию, хотя логичнее добавлять по мере надобности: выбрали элемент - открыли детали - нажали Назад - закрыли.
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
Вот несколько комментариев по вашему коду:
1. Дочерние фрагменты связаны общим классом Model - это как раз и есть связность. В предолженном мной варианте, дочерние фрагменты совершенно независимы и могу находится в разных модулях.
2. У Вас ListFragment умеет только сообщать о том, что выбран элемент. Ему не надо надо уметь читать listId из ListViewModel. Это нарушение I из SOLID.
3. Из пункта 2 вытекает то же самое для ListViewModel - она может только писать в Model. Опять нарушается I из SOLID - чтение должно быть недоступно.
4. Тоже самое для DetailsViewModel, ей не нужно уметь изменять listId
5. DetailsViewModel подписывается на Model, но не отписывается. Т.к. жизненный цикл Model потенциально может быть шире, можно получить утечку.
6. DetailsFragment не отписывается от DetailsViewModel - может быть утечка
7. Оба фрагемента сразу добавляются в иерархию, хотя логичнее добавлять по мере надобности: выбрали элемент - открыли детали - нажали Назад - закрыли.
1. Нет, фрагменты знают только про свою view model, про собственно Model нет
2. Ок, уберем геттер из ListViewModel.listId property
3. см п. 2
4. А она и не меняет, ее лист ид проперть рид онли
5. Нуу, я ж не писал полноценное приложение, я знаю, что не отписывается. Реализовать это можно элементарно в fragment lifecycle. A так-то можно и полноценную message bus замутить
6. Почему? Время жизни DetailsViewModel равно жизни фрагмента, пока существует фрагмент, существует и она. Без фрагмента она не существует. Если фрагмент уничтожается, ну да, вью модель надо отписывать от событий модели. Но зачем фрагменту отписываться от вью модели?
7. Втыкать фрагмент в существующую иерархию View это сильно дольше, чем прятать его, если мне не изменяет память.
По поводу I из SOLID - а где вы там specific interfaces увидели-то? Это данные, при чем тут интерфейсы. Это I - оно про узкую специализацию именно интерфейцев, типа вместо одного ISaveLoadVerifyAndUpload должно быть 4
источник

AI

Arkadii Ivanov in Android Architecture
Dm Savin
1. Нет, фрагменты знают только про свою view model, про собственно Model нет
2. Ок, уберем геттер из ListViewModel.listId property
3. см п. 2
4. А она и не меняет, ее лист ид проперть рид онли
5. Нуу, я ж не писал полноценное приложение, я знаю, что не отписывается. Реализовать это можно элементарно в fragment lifecycle. A так-то можно и полноценную message bus замутить
6. Почему? Время жизни DetailsViewModel равно жизни фрагмента, пока существует фрагмент, существует и она. Без фрагмента она не существует. Если фрагмент уничтожается, ну да, вью модель надо отписывать от событий модели. Но зачем фрагменту отписываться от вью модели?
7. Втыкать фрагмент в существующую иерархию View это сильно дольше, чем прятать его, если мне не изменяет память.
По поводу I из SOLID - а где вы там specific interfaces увидели-то? Это данные, при чем тут интерфейсы. Это I - оно про узкую специализацию именно интерфейцев, типа вместо одного ISaveLoadVerifyAndUpload должно быть 4
А "свои" модели знают напрямую про Model. Транзитивная зависимость не позволит разнести фрагменты по модулям.
источник

AI

Arkadii Ivanov in Android Architecture
7. Иметь несколько фрагментов друг над другом - это overdraw, который крайне не рекомендуется.
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
А "свои" модели знают напрямую про Model. Транзитивная зависимость не позволит разнести фрагменты по модулям.
Конечно знают, потому что это общие данные. Задача view models в том и состоит, чтоб выставить наружу для UI только то, что нужно конкретному UI
источник

AI

Arkadii Ivanov in Android Architecture
Ладно я устал спорить. Делайте как Вам надо.
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
7. Иметь несколько фрагментов друг над другом - это overdraw, который крайне не рекомендуется.
Даже если visibility = GONE?
источник

AI

Arkadii Ivanov in Android Architecture
А когда не GONE?
источник

AI

Arkadii Ivanov in Android Architecture
Начинается overdraw. А можн обыло List засунуть в backstack
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
Ладно я устал спорить. Делайте как Вам надо.
Дык я вам принципы MVVM цитирую, какой спор?
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
А когда не GONE?
Ну я-то их ставлю в gone. Это быстрее, чем их заново создавать каждый раз
источник

AI

Arkadii Ivanov in Android Architecture
Dm Savin
Ну я-то их ставлю в gone. Это быстрее, чем их заново создавать каждый раз
Извиняюсь, вы показали код, в котором есть связность компонентов. В моём коде она полностью отсутствует. MVVM здесь не причём. Если вам нужен обмен данными - используйте коллбеки, они для этого и предназначены. За сим я откланяюсь.
источник

Q

QMan in Android Architecture
Не понял: это где и у кого model что-либо вещает и от нее надо отписываться ?
источник

DS

Dm Savin in Android Architecture
Arkadii Ivanov
Извиняюсь, вы показали код, в котором есть связность компонентов. В моём коде она полностью отсутствует. MVVM здесь не причём. Если вам нужен обмен данными - используйте коллбеки, они для этого и предназначены. За сим я откланяюсь.
Ваш код прекрасен, вот только маинтейнить его будет ужасно
источник

Q

QMan in Android Architecture
извиняюсь что встреваю
источник