Course Content
-
Сохраняем данные в Room + ViewModel
- Коротко об Android Architecture Components и Room
- Создание проекта и добавление необходимых зависимостей
- Создание Entity
- Создание DAO
- Знакомство с LiveData
- Создание базы данных Room
- Знакомство с патерном Repository (Репозиторий) и создание слоя для доступа к данным
- Создание ViewModel
- Создание ячейки списка для отображения UI
- Создание адаптера и добавление RecyclerView
- Добавление записи в БД используя Room
- Создание Activity
- Подключение к базе данных Room
- Итоги
Создание ViewModel
ViewModel является частью lifecycle library и предоставляет данные для UI и умеет переживать изменения конфигурации. ViewModel является посредником между репозиторием и UI. Кроме того, вы можете использовать ViewModel для обмена данными между фрагментами.

Когда использовать ViewModel?
ViewModel содержит данные для UI и умеет корректно обрабатывать изменения конфигурации, то есть переживать пересоздание Activity/Fragment. Отдельное от Activity/Fragment хранение данных, который нужно отображать в UI позволяет следовать принципу единственной ответственности (single responsibility principle) Таким образом, пока Activity или Fragment нужны только для создания экрана, ViewModel в свою очередь занимается наполнением и обработкой данных, отображаемых в UI – элементах. Лучше всего использовать ViewModel совместно с LiveData для данных, которые могут изменится после отображения на экране. Использование LiveData имеет несколько преимуществ:
- Можно подписаться на обновление данных (вместо постоянной проверки на изменения вручную). Тогда UI обновится только в том случае, когда это необходимо, то есть когда изменятся данные.
- Репозиторий (как источник данных) и UI полностью разделены и общаются через
ViewModel. - Не нужно делать запросы в БД из
ViewModel(эта логика реализуется в репозитории). Это делает код более тестируемым.
viewModelScope
В Kotlin все корутины запускаются в так называемом CoroutineScope Скоупы контролиуруют время жизни корутин. Когда вы отменяете задачу в скоупе, то отменяются все корутины запущенные в этом скоупе. Библиотека lifecycle-viewmodel-ktx являющаяся частью AndroidX имеет расширениеviewModelScope позволяющее работать со скоупами.
Создание ViewModel
Создадите класс WordViewModel как показано ниже
// Class extends AndroidViewModel and requires application as a parameter.
class WordViewModel(application: Application) : AndroidViewModel(application) {
// The ViewModel maintains a reference to the repository to get data.
private val repository: WordRepository
// LiveData gives us updated words when they change.
val allWords: LiveData<List<Word>>
init {
// Gets reference to WordDao from WordRoomDatabase to construct
// the correct WordRepository.
val wordsDao = WordRoomDatabase.getDatabase(application).wordDao()
repository = WordRepository(wordsDao)
allWords = repository.allWords
}
/**
* The implementation of insert() in the database is completely hidden from the UI.
* Room ensures that you're not doing any long running operations on
* the main thread, blocking the UI, so we don't need to handle changing Dispatchers.
* ViewModels have a coroutine scope based on their lifecycle called
* viewModelScope which we can use here.
*/
fun insert(word: Word) = viewModelScope.launch {
repository.insert(word)
}
}
Как обычно, давайте разберём, что здесь есть:
- Класс
WordViewModelпринимаетApplicationв качестве аргумента и наследуется отAndroidViewModel. val repositoryявляется приватным свойством для хранения ссылки на репозиторий.- Для кэширования списка слов добавим публичное свойство
val allWords: LiveData<List<Word>> initблок инициализирует переменнубwordDaoявляющейся экземпляромWordDaoизWordRoomDatabase.- В
initблоке инициализируется через репозиторий переменная LiveDataallWords - Метод
insert()является методом – обёрткой для вызова методаinsert()в репозитории. Так как работать с БД рекомендуется в отдельном потоке мы используем корутины для вызова метода в отдельном потоке, на случай если вставка элемента затянется, то мы не будем блокировать главный поток, а значит для пользователя работа приложения будет максимально удобной.
В следующих уроках мы создадим UI для отображения данных на экране приложения.