Содержание статьи

При смене конфигурации Activity уничтожается, но данные, размещённые во ViewModel, остаются доступными. Это достигается за счёт отдельного хранилища – ViewModelStore, которое не сбрасывается вместе с Activity. Такой подход снижает объём пересоздаваемых объектов и уменьшает количество запросов к источникам данных.
Экземпляр ViewModel создаётся через ViewModelProvider. Провайдер проверяет, существует ли объект в ViewModelStore, и возвращает его без повторной инициализации. Благодаря этому сохраняются результаты вычислений, состояния экранных моделей и промежуточные данные.
При использовании ViewModel важно соблюдать ограничение: хранить только данные, необходимые для логики UI, а не объекты, завязанные на контекст Activity. Это позволяет избежать утечек памяти и сохранять корректное поведение после пересоздания экрана.
Создание ViewModel через ViewModelProvider и роль фабрики
ViewModelProvider формирует экземпляр ViewModel на основе ключа и хранилища ViewModelStore. При обращении к провайдеру выполняется проверка: если объект уже создан, он возвращается без повторного запуска конструктора. Это позволяет сохранять состояние между пересозданиями Activity.
Когда ViewModel требует параметров, используется ViewModelProvider.Factory. Фабрика управляет созданием экземпляра и предотвращает ошибки, возникающие при попытке обращаться к конструкторам напрямую. Такой подход позволяет передавать в ViewModel репозитории, сервисы или идентификаторы, не нарушая архитектурные ограничения.
| Компонент | Назначение |
|---|---|
| ViewModelProvider | Получение существующей ViewModel или создание новой |
| ViewModelStore | Хранение экземпляров между пересозданиями Activity |
| Factory | Создание ViewModel с параметрами и контролем зависимости |
При использовании фабрики предпочтительно выносить её реализацию в отдельный класс. Это облегчает тестирование и уменьшает количество логики в Activity или Fragment. Такой подход помогает поддерживать структуру проекта и упрощает расширение экранных моделей.
Механизм хранения экземпляра ViewModel в ViewModelStore
ViewModelStore представляет собой контейнер, в котором экземпляры ViewModel сохраняются под уникальными ключами. Каждый ключ соответствует конкретному владельцу жизненного цикла. Пока владелец не уничтожен окончательно, данные внутри контейнера остаются доступными.
При пересоздании Activity фреймворк восстанавливает ViewModelStoreOwner и передаёт в него прежний ViewModelStore. Благодаря этому ViewModel не инициируется повторно, а продолжают существовать уже созданные экземпляры. Такой механизм избавляет от необходимости вручную восстанавливать данные, полученные из репозиториев или сетевых источников.
Удаление объекта происходит только при вызове onCleared, который срабатывает в момент окончательного уничтожения владельца. Этот подход защищает ViewModel от преждевременного освобождения и обеспечивает предсказуемое время жизни модели.
Что происходит с ViewModel при уничтожении и повторном создании Activity

При уничтожении Activity из-за смены конфигурации система удаляет только саму Activity и её представление. ViewModel при этом не затрагивается, так как хранится в ViewModelStore, связанного с предыдущим экземпляром владельца.
После пересоздания Activity фреймворк формирует новый ViewModelStoreOwner и подключает к нему прежний ViewModelStore. Провайдер извлекает уже существующий объект и передаёт его новой Activity. Конструктор ViewModel не вызывается повторно, что сохраняет накопленные данные и состояние экранной логики.
Если же Activity завершается окончательно, ViewModelStore удаляется, а ViewModel получает сигнал onCleared. Этот момент указывает на то, что экземпляр более не будет использоваться и может освободить ресурсы, например закрыть потоки или отменить задачи.
Как работает привязка ViewModel к жизненному циклу владельца

Привязка ViewModel к владельцу жизненного цикла определяется объектом ViewModelStoreOwner. Каждый владелец предоставляет ViewModelStore, и провайдер использует его для поиска или создания экземпляров. Пока владелец находится в активном состоянии, ViewModel остаётся доступной.
- ViewModel создаётся только один раз для конкретного владельца и не пересоздаётся при смене конфигурации.
- Жизненный цикл владельца контролирует момент вызова onCleared, что позволяет выполнять завершающие операции.
- Fragment и Activity используют независимые хранилища, поэтому ViewModel нужно создавать у того владельца, которому принадлежат данные.
Правильная привязка позволяет разделять ответственность: Activity управляет отображением, а ViewModel отвечает за подготовку данных. Это снижает риск ошибок при взаимодействии с моделью и упрощает сопровождение кода.
Поведение ViewModel при смене конфигурации и почему она не пересоздаётся

Смена конфигурации вызывает уничтожение Activity, однако ViewModel остаётся в памяти, так как хранится в ViewModelStore. Это хранилище не привязано к самому экрану и не сбрасывается при пересоздании интерфейса.
При запуске нового экземпляра Activity система передаёт ему прежний ViewModelStoreOwner. ViewModelProvider использует тот же ключ и извлекает существующий объект. Благодаря этому сохраняются результаты операций, выполненные в предыдущем экземпляре экрана.
Чтобы ViewModel корректно переживала изменение ориентации или другие конфигурационные события, важно не включать в неё ссылки на Activity или элементы интерфейса. Это предотвращает утечки памяти и поддерживает стабильность работы модели при повторных пересозданиях владельца.
Очистка ViewModel: вызов onCleared и условия его выполнения
Метод onCleared вызывается, когда ViewModel окончательно теряет владельца жизненного цикла. Это происходит только при полном уничтожении Activity или Fragment, а не при смене конфигурации. В этот момент можно завершить фоновые задачи, закрыть потоки и освободить ресурсы.
Важно не помещать объекты, завязанные на контекст Activity или Fragment, непосредственно в ViewModel, иначе они могут блокировать очистку. Вместо этого следует использовать ссылки на репозитории или сервисы, не зависящие от интерфейса.
onCleared гарантирует точку завершения работы модели, позволяя управлять памятью и предотвращать утечки. Любые операции, которые должны выполняться один раз после завершения жизненного цикла владельца, следует помещать именно сюда.
Вопрос-ответ:
Почему ViewModel не пересоздаётся при смене ориентации экрана?
ViewModel хранится в ViewModelStore, который не уничтожается при пересоздании Activity из-за смены конфигурации. При повторном создании Activity ViewModelProvider извлекает уже существующий объект, поэтому конструктор модели не вызывается повторно, а данные сохраняются.
Как передать параметры в ViewModel при её создании?
Для передачи параметров используют ViewModelProvider.Factory. Фабрика создаёт экземпляр модели с необходимыми аргументами, такими как репозитории или идентификаторы, обеспечивая корректную инициализацию без прямого вызова конструктора внутри Activity.
Что происходит с ViewModel при полном уничтожении Activity?
При окончательном уничтожении Activity или Fragment ViewModelStore удаляется, и метод onCleared вызывается для освобождения ресурсов. Это позволяет закрыть потоки, отменить задачи и предотвратить утечки памяти.
Можно ли хранить в ViewModel ссылки на элементы интерфейса?
Нельзя помещать объекты, завязанные на Activity или Fragment, напрямую в ViewModel. Это может блокировать очистку модели и приводить к утечкам памяти. Вместо этого следует хранить только данные и логические объекты, не связанные с конкретным экраном.
Как ViewModel взаимодействует с жизненным циклом Fragment и Activity?
ViewModel привязана к владельцу жизненного цикла через ViewModelStoreOwner. Она остаётся доступной, пока владелец активен, и уничтожается только при окончательном завершении жизненного цикла. Это позволяет разделять подготовку данных и отображение без потери состояния при пересоздании интерфейса.
Почему данные во ViewModel сохраняются после пересоздания Activity?
ViewModel хранится в отдельном контейнере ViewModelStore, который не уничтожается при смене конфигурации Activity. При пересоздании экрана ViewModelProvider проверяет наличие существующей модели в хранилище и возвращает её, что позволяет сохранить состояние и результаты предыдущих операций без повторного создания.
Как правильно использовать onCleared для освобождения ресурсов во ViewModel?
Метод onCleared вызывается только при окончательном уничтожении владельца жизненного цикла. В нём следует завершать фоновые задачи, закрывать потоки и освобождать объекты, завязанные на внешние ресурсы. Это предотвращает утечки памяти и обеспечивает корректное завершение работы модели.
