Где хранится ViewModelStore?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Хранение ViewModelStore в Android Architecture Components
ViewModelStore — это ключевой компонент архитектуры Android Jetpack, который отвечает за хранение и управление экземплярами ViewModel. Его расположение и жизненный цикл тесно связаны с компонентами, которые используют ViewModel.
Основные места хранения ViewModelStore
1. В компоненте Activity через ComponentActivity
В современных Android-приложениях ViewModelStore хранится в ComponentActivity (или AppCompatActivity, которая наследуется от нее). ComponentActivity реализует интерфейс ViewModelStoreOwner и содержит поле mViewModelStore.
// Упрощенная реализация из исходного кода ComponentActivity
public class ComponentActivity extends androidx.core.app.ComponentActivity
implements ViewModelStoreOwner {
private ViewModelStore mViewModelStore;
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
return mViewModelStore;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
mViewModelStore.clear();
}
}
}
2. В компоненте Fragment через FragmentActivity
Для фрагментов ViewModelStore хранится в их FragmentManager, что позволяет ViewModel переживать изменения конфигурации отдельного фрагмента:
// ViewModel хранится в FragmentManagerViewModelsStore
class Fragment implements ViewModelStoreOwner {
private ViewModelStore mViewModelStore;
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
return mViewModelStore;
}
}
3. В Navigation Component для графа навигации
С появлением Navigation Component появилась возможность хранить ViewModelStore в NavController, что позволяет ViewModel существовать в пределах графа навигации:
// ViewModel привязанный к графу навигации
val navController = findNavController()
val viewModel: MyViewModel by navController.navGraphViewModels(R.id.nav_graph)
Архитектурные детали реализации
Структура хранения:
- ViewModelStore internally uses a
HashMap<String, ViewModel>для хранения экземпляров ViewModel - Ключом обычно является каноническое имя класса ViewModel с дополнительными идентификаторами
// Упрощенная внутренняя структура ViewModelStore
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
public final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
public final ViewModel get(String key) {
return mMap.get(key);
}
}
Жизненный цикл и очистка:
- Для Activity: ViewModelStore очищается только когда Activity завершается окончательно (
isFinishing() == true) - Для Fragment: ViewModelStore очищается когда Fragment полностью уничтожается
- При изменении конфигурации (поворот экрана) ViewModelStore сохраняется через механизм onRetainNonConfigurationInstance()
Важные аспекты:
- ViewModelStore создается лениво — только при первом запросе ViewModel
- Кэширование в ViewModelProvider: ViewModelProvider кэширует созданные ViewModel в ViewModelStore
- Множественные ViewModelStore: В приложении может быть несколько ViewModelStore (для разных Activity, Fragment, navigation graphs)
- Безопасность при многопоточности: Доступ к ViewModelStore должен осуществляться из главного потока
Практическое значение
Понимание где хранится ViewModelStore важно для:
- Отладки утечек памяти — знание жизненного цикла помогает предотвратить memory leaks
- Кастомизации Scope — создания собственных областей видимости для ViewModel
- Оптимизации производительности — правильного управления жизненным циклом ViewModel
- Тестирования — мокирования или замены ViewModelStore в instrumented tests
Ключевой вывод: ViewModelStore является неотъемлемой частью инфраструктуры Android Jetpack, которая обеспечивает правильный жизненный цикл ViewModel, их сохранение при изменениях конфигурации и своевременную очистку для предотвращения утечек памяти. Его расположение варьируется в зависимости от компонента-владельца (Activity, Fragment или NavController), но всегда соответствует жизненному циклу этого компонента.