Pull to refresh

Comments 23

Зачем LiveData в вашем случае? Уже есть Flow, который также работает на скоупе жизненного цикла… Как плюс — отсутсвие маппинга Flow/Rx <-> LiveData.

Мы используем Flow в репозиториях. Есть задачи, где стримы и трансформации удобны? но от маппинга это не освобождает. API всегда маппится и живет своей жизнью (однажды это мне очень помогло). Сценарии тоже выдают, так сказать, PresentationViewModel, внутри которых спрятано много логики. Можно LiveData заменить на Flow, если угодно. Но мне кажется, что LiveData во ViewModel удобнее и проще. Их цель просто передать состояние для View.
Но мне кажется, что LiveData во ViewModel удобнее и проще

Вот тут хотелось бы развёрнуто… Просто я вижу много примеров как под копирку, что во вью слое используется LiveData и не могу понять преимущества.
А с учётом того, что Гугл уже активно пиарит и поддерживает корутины, то будет также активно пиарить и Flow(и судя по последним коммитам Flow уже выходит из стадии Experimental), а LiveData они задиприкейтят через какое-то время..

Потому, что Вы забываете про смену конфигурации. Она произойдет, хотите Вы этого или нет. В этом случае активити или фрагмент (View) будут пересозданы. Задача ViewModel в этом случае — перенести данные и отдать последние известные состояния View.
Здесь и видна разница между Flow и LiveData. Это разного порядка инструменты.
Flow — просто реактивный поток, способ организации следующих друг за другом событий. Он ничего в себе не хранит и при следующей подписке, в общем случае, запустит заложенный в него код заново.
LiveData — это mutable storage (цитата с IO19). Его задача — отдать последнее известное ему значение. В случае конвертации toLiveData() — последний отданный flow результат.
Итого, предположим, у Вас сетевой запрос завернут в flow{}. Без конвертации в LiveData внутри ViewModel, этот запрос будет выполняться при каждом, например, повороте экрана. LiveData решает в том числе и эту проблему.
а LiveData они задиприкейтят через какое-то время..
Нет. На IO уже не один раз говорили, что это разного рода инструменты с разным назначением. Потому деприкейт если и будет, то очень не скоро.

Поспорю)


LiveData — это mutable storage

Всё это есть в любой реактивщине. В Rx — всякие PublishProcessor/BehaviorProcessor и т.д.(бывшие xxxSubject)
В Flow — пока ещё ConflatedBroadcastChannel и скорый StateFlow


К тому же есть ViewModel, которая также переживает смену конфигурации и прочее.

Не в любой, но есть. Однако, все эти реализации интегрируются с жизненным циклом гораздо хуже LiveData. По своему опыту могу сказать, что со сторонними реактивными реализациями пока слишком много проблем.
Плюс ко всему, LiveData используется не только как прокладка между Rx и Flow.
Например, как управляющая компонента. Или в составе той же paging library.
ConflatedBroadcastChannel и скорый StateFlow
В них еще не скоро будет интеграция с LifeCycleOwner и прочими вещами. Всё-таки Flow — часть Kotlin Coroutines, а не Android. А даже если появится, то будем использовать прокладку в виде еще одного Flow вместо LiveData так как хранить состояние в UseCase не всегда нужно и редко полезно.
К тому же есть ViewModel
Вы опять смешиваете инструменты)
ViewModel сама по себе не решает задачу управления View в рамках жизненного цикла. Этим и занимается LiveData. На ViewModel же ложится задача переносить эти LiveData и содержать логику, которая управляет данными в LiveData.

Оценивайте тенденции) Лично я вижу, что скорость принятия и адаптации корутин очень быстрая. А появление LiveData ждали очень много времени.
Rx я думаю, тоже скоро начнут забывать… А вот у Flow есть очень много шансов.
Даже с учётом экспериментального статуса уже сейчас есть начальная поддержка ЖЦ хотя бы для автоматической отписки.


А даже если появится, то будем использовать прокладку в виде еще одного Flow вместо LiveData так как хранить состояние в UseCase не всегда нужно и редко полезно.

Ну тут не очевидно, а зачем хранить промежуточное состояние в LiveData во ViewModel? Зачем этот промежуточный слой хранения? Состояние хорошо бы хранить только в репозитории, но хотя это добавляет проблему лишних цепочных преобразований данных при смене конфигурации.


Вы опять смешиваете инструменты

Я не смешиваю, просто выше была на мой взгляд не совсем верная формулировка, что LiveData переживает ЖЦ, но она не может его переживать просто так) Это контейнер, где она хранится переживает конфигурации.

Rx я думаю, тоже скоро начнут забывать…
Если Вы о RxJava от ReactiveX, то не скоро. Я хоть и сам широко использую Flow и корутины, но вакансий, где требуют RxJava и ее сторонников на руководящих должностях еще много. Людям не просто отпускать привычное.
Зачем этот промежуточный слой хранения?
Потому, что нужно разделять бизнес-логику и презентационную логику. Состояние далеко не всегда хорошо хранить в репозитории из-за того, что большинство операций повторяемые. Иначе это мало будет отличаться от поделок на EventBus 5 летней давности.
на мой взгляд не совсем верная формулировка
Тут согласен. LiveData, скорее, работает с ЖЦ Observer. Обычно это View, однако та же Navigation Library предлагает интересные приемы с LiveData.
Оценивайте тенденции)
Да, есть такая тенденция. Но до ее реализации еще далеко. А до тех пор стабильнее LiveData для выше обозначенных задач нет ничего, и с ней в прод еще ходить как минимум год.
Людям не просто отпускать привычное.

Как вы можете отпустить привычное, когда проект просто огромный? А дописывать новый функционал на корутинах создаст только большие проблемы.
Имею много позитивного опыта по прикручиванию нового функционала на корутинах, архитектурных компонентах и так далее к легаси различной древности и размерности. Но да, это не всегда целесообразно.
Но речь шла именно о новых проектах. Тут, скорее, либо инерция, либо попытка доказывать профессионализм на волне чьего-то успеха.
Не проще использовать DataBinding который намного удобнее той же LiveData и позволяет сократить кол-во кода?
В Android я пришел из C#, после WPF DataBinding на андроид не воспринимается. Но, в общем, DataBinding отлично подходит в этой архитектуре. Я просто не считаю его проще и удобнее. Описание данных в xml, адаптеры…
Не понял, какие адаптеры? Databinding позволяет напрямую прокидывать клики или получать данные из ViewModel-и
Да, в простом случае можно сразу биндить click. Но тут не совсем понятно, как передавать параметры, например, если View фрагмента состоит из нескольких layout, и одному из них надо запустить команду с параметрами другого layout. Также целесообразно использовать DataBinding везде, например, в сложных списках, в общем, BindingAdapters всегда вылезают. Был у меня проект, где дизайнеры такого выдумали, что в некоторых случаях сбиндить не удалось (может, не хватило знаний и умений), и в коде стали использоваться оба подхода. Ещё мне не нравится код в xml, какой-то возврат к истокам, сначала все бились над разделением кода и дизайна, теперь в дизайн добавляем логику, модели данных. Это, конечно, субъективно и навеяно опытом работы с ASP.NET.
Но тут не совсем понятно, как передавать параметры, например, если View фрагмента состоит из нескольких layout, и одному из них надо запустить команду с параметрами другого layout

Первый ответ со стеф оверфлоу) bind:viewModel="@{viewModel}" — если конечно я правильно понял вопрос
Также целесообразно использовать DataBinding везде, например, в сложных списках, в общем, BindingAdapters всегда вылезают.

Адаптеры нужны для чего-то специфического, например засетить картинку в ImageView. Адаптеры же RecyclerView засечиваются напрямую, он же работает через сеттеры обычные. Кидайте хоть TextWatcher из ViewModel
Он не решает задачи смены конфигурации и хранения состояния. В ветке выше описал подробнее.
Ну что, круто, я сам делаю так же само почти год уже. Если правильно организовать исходный код — то бонусом можно получить kotlin-multiplatform (:
Почему сценарий преобразовывает данные для представления? Для этого ему нужно знать о представлении, которое слоем выше, и подстраиваться под него.
Нет, логика ничего не знает о представлении. В идеале андроид можно заменить на что угодно, например, на веб. Это архитектура хорошо работает на ксамарин, где у меня есть 4 разных UI с общей логикой. Сценарий возвращает модель согласно User Story или фичи, которую дают менеджеры. Например: нужно отобразить список файлов и список участников, для которых файл доступен для редактирования, отсортированный по некоторому признаку. Логика обратится к нужным репозиториям, отфильтрует и вернет готовый список в виде простой модели, в которой есть только то, что нужно по этому сценарию. Логика ничего не знает о UI. UI принимает модель от логики (ui ссылается на модель логики), UI должен знать, что в этой модели хранится и как ее отобразить, а не наоборот. Может показаться, что логика подстраивается под UI, на самом деле и логика, и UI подстраиваются под ваши User Stories.
В случаях, когда одна и та же порция данных нужна двум экранам, причём в разном формате, получатся два сценария, делающих почти одинаковые действия? Вопроса бы не было, если бы в примере LoginUseCase не определял цвет текста, а передавал статус пользователя, по которому в VM/Activity определялся бы цвет. Но тут задействованы именно нюансы интерфейса.
Может, цвет не самый лучший пример получения каких-то данных путем расчета в логике приложения. Это не цвет из дизайна, конечно же. Например, цвет назначается для пользователя с определенным уровнем доступа. Т.е. этот параметр обладает логикой. Ваш пример с 2-я экранами: я бы сделал общий UseCase, который получает необходимые данные. И два UseCase для каждого экрана, каждый из которых включает предыдущий общий UseCase. Т.к. каждый UseCase получает данные из общего (DRY) и формирует ответ согласно своей логике, заданной в User Story.
А что мы в теории потеряем, если вынесем этот маппинг на ViewModel, вместо создания разных UseCase?
Переиспользование и разбросанное тестирование. UseCase можно использовать в любом месте, а не только во ViewModel. У меня в проекте они подключаются в сервисах, ресиверах, да где угодно. И везде используются сценарии, которые уже хорошо отлажены. Плюс, когда я написал сценарий, я сразу могу написать для тесты и проверить, что все правильно. И тесты логики находятся в одном месте вместе с реализацией.
Sign up to leave a comment.

Articles