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

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

Возникает логичный вопрос: зачем городить огород с прокидыванием моделей внутрь XML-файлов, вызывать в XML-файлах Java-методы, перегружать логику XML-части, если всего этого можно избежать?

А кто сказал, что это все необходимо при использовании Data Binding? Все что требуется это объявить переменную в начале файла, и затем ссылаться на нее в XML:
android:text=@{viewModel.text}

все функции обработки должны быть вынесены в сторонние классы и файлы («Presenters»), дабы не загромождать ViewModel и не отвлекать от сути.

Почему не Interactor или Usecase?
В результате архитектура стала кристально чистой, что является большим плюсом.

Если под чистой вы имеете ввиду Clean Architecture, то нет, получилась совсем не она.
Выглядит она примерно так: View -> ViewModel -> Interactor -> Repository. Уж точно без всяких классов Presenter, принадлежащих фрагментам. View должен делать одно и только одно: мапить уже подготовленные данные в лэйаут, без каких либо дополнительных преобразований, неважно используя синтетические импорты ли или Data Binding.
Kotlin старается защитить программиста от некорректного написания кода, поэтому мы должны либо сразу сказать, что объект может быть null, либо поставить lateinit.


вот прям кусок кода из оф документации без того и другого:
val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}


В общем текст неплохой, но уж больно безапелляционный, с кучей маркетинговых словечек и фактических ошибок. Извините.

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

Все что требуется это объявить переменную в начале файла, и затем ссылаться на нее в XML
+ обернуть все в

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="viewmodel"
            type="com.myapp.data.ViewModel" />
    </data>
    <ConstraintLayout... /> <!-- UI layout's root element -->
</layout>

И конечно, это самый простой случай использования data binding. Если же нужно проверить и обработать данные та же google-документация рекомендует писать так:

android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'


Не знаю, как Вас, но меня скручивает от возможности написать такое. Это выглядит программированием из 2000-х или даже из 90-ых. Синтаксис и конструкции морально устарели, и нуждаются в качественном осовременивании. На всякий случае, еще раз скажу — я не против data binding, но только там, где он по-настоящему уместен. Без острой нужды, я не стану им пользоваться.

Почему не Interactor или Usecase?

При использовании Interactor получается идеально кристальные фрагменты и активити, которые служат только для обновления UI (если все сделать правильно). Полагаю, для крупных проектов такой подход имеет очевидные преимущества, но для небольших проектов разница едва ли будет заметна. И в случае с Presenter, и в случае с Interactor результат будет аналогичным — фрагменты и активити будут чисты от data-преобразований.

val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}


На сколько я помню, этот код выполняет отложенную инициализацию: при первом обращении к переменной lazyValue, присвоить ей значение «Hello» и вывести в консоль «computed!». Переменная так или иначе была проинициализирована, она не обрели 3-го состояния между Null и lateinit. Разумеется, Kotlin не защитит разработчика от желания стрелять себе в ноги, но значительно снизить эту вероятность. Думаю Вы с этим согласитесь.

P.S. искренни благодарен за feedback.
Если же нужно проверить и обработать данные та же google-документация рекомендует писать так:

Это все прекрасно может жить во ViewModel. Поверьте, и Гугл может быть не прав ))
При использовании Interactor получается идеально кристальные фрагменты и активити, которые служат только для обновления UI (если все сделать правильно). Полагаю, для крупных проектов такой подход имеет очевидные преимущества, но для небольших проектов разница едва ли будет заметна.

То есть если надо один гвоздь забить, а не десять — это можно делать тяп-ляп?))

Переменная так или иначе была проинициализирована, она не обрели 3-го состояния между Null и lateinit.

Хорошо, в каком она состоянии до первого обращения к ней?
Если проект отличается от используемого вами патерна, это совсем не значит проект написан плохо. Послушать вас, так все MVP-проекты — «тяп-ляп», там знаете ли тоже presenter-ы есть)) Что же касается ленивого объявления, то в каком именно состоянии находится переменная до инициализация делигатом — документация умалчивает. Логично было бы предположить, что до вызова setValue (метода делигата) переменная находится в неопределенном состоянии. Однако, без вскрытия компилятора вы никак не получите ее в этом состоянии. Отсюда у меня возникает логичный вопрос: зачем было приводить этот пример в самом начале, если ленивая инициализация не меняет принципов разработки? Идея lateinit и объявления переменной null заключается в том, чтобы свести вероятность NullPointerException к нулю, и конечно lazy-инициализация не нарушает этой идеи.
Если проект отличается от используемого вами патерна, это совсем не значит проект написан плохо. Послушать вас, так все MVP-проекты — «тяп-ляп», там знаете ли тоже presenter-ы есть))

Пардон, но статья о MVVM, а там Presenter отсутствует в принципе.
Отсюда у меня возникает логичный вопрос: зачем было приводить этот пример в самом начале, если ленивая инициализация не меняет принципов разработки?

Затем, чтобы опровергнуть постулат о том, что мы ДОЛЖНЫ использовать или Nullable переменную или lateinit.
Что же касается ленивого объявления, то в каком именно состоянии находится переменная до инициализация делигатом — документация умалчивает.

Можно написать простейший код, поставить точку останова и посмотреть, если интересно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий