Когда целесообразно использовать MVVM

Ответ

MVVM особенно полезен, когда нужно разделить логику представления (UI) от бизнес-логики, обеспечивая тестируемость и поддержку. Основные сценарии:

  1. Data Binding - автоматическое обновление UI при изменении данных
  2. Жизненный цикл - ViewModel сохраняет состояние при повороте экрана
  3. Тестирование - бизнес-логика тестируется без Android-зависимостей

Пример:

class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<String>()
    val data: LiveData<String> = _data

    fun loadData() {
        _data.value = "Loaded data"
    }
}

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val viewModel = ViewModelProvider(this)[MyViewModel::class.java]
        viewModel.data.observe(this) { data ->
            textView.text = data
        }
    }
}

Ответ 18+ 🔞

А, ну MVVM, ёпта! Смотри, чтобы ты не сдох от этой архитектуры, я тебе на пальцах объясню, что это за хитрая жопа такая.

Представь, что твой UI — это тупой красавчик, который только и умеет, что кнопки тыкать и текст показывать. А бизнес-логика — это его мозг, который где-то там, в другом месте, реально думает. Так вот, MVVM — это чтобы этот красавчик-интерфейс и его мозг жили отдельно, не мешая друг другу. Идея проще пареной репы: ты можешь мозги (логику) тестировать отдельно, не таская за собой всю эту жирную Android-зависимость, которая жрёт память, как не в себя.

Основные плюсы, ради которых всё это затеяли? Их, бля, овердохуища, но главные три:

  1. Data Binding (привязка данных) — это вообще магия, чувак. Ты в коде поменял значение, а UI сам, без твоих кривых рук, обновился. Никаких textView.text = "опять я". Сделал раз — и забыл. Красота.
  2. Жизненный цикл — вот тут реально спасение. Ты поворачиваешь экран, а твоя ViewModel (это та самая прослойка-мозг) не накрывается медным тазом. Все данные на месте, состояние сохранилось. Не надо эти костыли с onSaveInstanceState везде пихать, ёб твою мать.
  3. Тестирование — а вот это вообще пиздец как важно. Ты можешь взять свою ViewModel, оторвать её от всей этой Android-библиотечной хуеты, и проверить, правильно ли она считает или данные грузит. Без эмуляторов, без ожиданий. Чистая логика. Доверия ебать ноль к тому, что работает только на твоём телефоне.

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

class MyViewModel : ViewModel() {
    // Внутри храним изменяемые данные, но наружу отдаём только для чтения
    private val _data = MutableLiveData<String>()
    val data: LiveData<String> = _data

    // А это наша бизнес-логика, которую можно тестировать
    fun loadData() {
        _data.value = "Loaded data"
    }
}

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Достаём нашу ViewModel
        val viewModel = ViewModelProvider(this)[MyViewModel::class.java]

        // Подписываемся на данные. Как только они поменяются — текст сам обновится.
        viewModel.data.observe(this) { data ->
            textView.text = data // Всё, больше ничего делать не надо. Красота.
        }
    }
}

Вот и вся магия. Сначала кажется, что ядрёна вошь, много лишних движений. Но когда проект растёт, и в этой Activity уже не 100, а 500 строк кода, ты понимаешь, что без такого разделения ты просто полупидор, который сам себе копает яму. А так — всё по полочкам, логика отдельно, вьюхи отдельно. Удобно, тестируемо, и голова не болит.