Архитектура Android приложений подразумевает сохранение и восстановление состояния Activity. В этом помогают ViewModel и LiveData. Два мощных компонента, которые являются частью Android Jetpack.
Жизненный цикл Activity
Давайте для начала совсем чуть-чуть поговорим об архитектуре Activity как основном компоненте ваших Android приложений. Вероятно вы знаете, что система может пересоздавать эти самые Активити. Например, когда оно в фоне и системе нужны ресурсы, или вы просто повернули экран и для необходимо пересоздать весь UI.

Вся сложность состоит в том, что для пользователя это не очевидно. Он вполне обоснованно предполагает, что приложение живет до тех пока не закрыто. Усугубляется это и тем, что в приложении с несколькими Activity для пользователя переходы между активностями не заметны. При переходе «назад» без сохранения состояния мы увидим не то что ожидаем, а начальное состояние.
Отсюда возникает необходимость хранить некое состояние — будь то загруженные данные или текущие переменные. Для этого и создан ViewModel. А для передачи информации — LiveData. Вот о них и поговорим.
Android ViewModel
ViewModel создан для того, чтобы хранить и управлять данными, которые относятся к UI (в нашем случае, например к Activity), но с учетом lifecycle. Т.е. он переживает и пересоздание всего компонента. Это хорошо видно на картинке:

ViewModel без контекста
В самом простом (и по сути правильном) варианте ViewModel создается путем наследования от класса ViewModel
class MyViewModel : ViewModel()...
Получить доступ к созданной ViewModel можно одной строчкой в вашей Activity
или Fragment
val model: MyViewModel by viewModels()
ViewModel с доступом к контексту
Если вам нужен доступ к контексту приложения, то существует реализация AndroidViewModel. Но я рекомендую стараться использовать базовый ViewModel в котором нет контекста. Так архитектура получается более консистентная и простая.
ViewModel можно использовать для взаимодействия между двумя фрагментами. Т.е. использовать одну разделяемую модель данных.
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
// Use the 'by activityViewModels()' Kotlin property delegate
// from the fragment-ktx artifact
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
// Use the 'by activityViewModels()' Kotlin property delegate
// from the fragment-ktx artifact
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
// Update the UI
})
}
}
Забегая вперед хочу сказать, что делать я бы так не советовал. Я пробовал 🙂 В итоге shared ViewModel становится довольно громоздкой и рискует превратится в God object. Лучше разделить модели относительно экранов, а общие данные хранить ниже — на уровне Repository.
Теперь рассмотрим как передавать данные из ViewModel непосредственно в ваши View.
Android LiveData
Для передачи данных из ViewModel в Android Jetpack также есть LiveData. Это объект с данным, которые предоставляет доступ к информации в потоковом режиме (observable). Если вы знакомы с rx, то найдете много общего по замыслу. Важное различие в том, что LiveData учитывает Lifecycle того, в чьем контексте работает. Другими словами закрывать его принудительно руками не нужно.
Для использования LiveData достаточно объявить её в вашей ViewModel.
class NameViewModel : ViewModel() {
// Create a LiveData with a String
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
Теперь внутри Activity, где хотите «слушать» данные устанавливаем observer.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other code to setup the activity...
// Create the observer which updates the UI.
val nameObserver = Observer<String> { newName ->
// Update the UI, in this case, a TextView.
nameTextView.text = newName
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.currentName.observe(this, nameObserver)
}
Теперь вы на базовом уровне знаете как использовать и для чего нужны ViewModel и LiveData.
Кстати, Google в рамках Android Jetpack представил много интересных инструментов, не только эти два. И да, я уже рассказывал про полезные библиотеки для Android разработчика.