Когда создается новый экземпляр ViewModelProvider
, первый параметр - activity.getViewModelStore()
и, согласно документации,
Возвращает {@link ViewModelStore}, связанный с этим действием
Переопределение этот метод больше не поддерживается, и этот метод будет установлен final
в будущей версии ComponentActivity. @return a {@code ViewModelStore} @throws IllegalStateException, если вызывается до того, как Activity прикреплена к экземпляру приложения, т. е. перед onCreate ()
возвращает объект ViewModelStore
. Так что же такое ViewModelStore
?
/**
* Class to store {@code ViewModels}.
* <p>
* An instance of {@code ViewModelStore} must be retained through configuration changes:
* if an owner of this {@code ViewModelStore} is destroyed and recreated due to configuration
* changes, new instance of an owner should still have the same old instance of
* {@code ViewModelStore}.
* <p>
* If an owner of this {@code ViewModelStore} is destroyed and is not going to be recreated,
* then it should call {@link #clear()} on this {@code ViewModelStore}, so {@code ViewModels} would
* be notified that they are no longer used.
* <p>
* Use {@link ViewModelStoreOwner#getViewModelStore()} to retrieve a {@code ViewModelStore} for
* activities and fragments.
*/
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
По сути, это класс с HashMap
, ключ которого равен DEFAULT_KEY + “:” + canonicalName
, где DEFAULT_KEY
равен androidx.lifecycle.ViewModelProvider.DefaultKey
, а значение равно ViewModel
Это означает, что каждая активность и фрагмент имеют ViewModelStore
, который сохраняет все объявленные ViewModels
в активности или фрагменте соответственно.
Но как ViewModelStore
переживает изменение ориентации?
В документации ViewModelStore
определено, что
, если владелец этого {@code ViewModelStore} уничтожен и воссоздан из-за изменений конфигурации *, новый экземпляр владельца все еще должен иметь тот же старый экземпляр * {@code ViewModelStore}.
Так что ответственность за действия - сохранить ViewModelStore
во время смены ориентации.
Если мы go вернемся к activity.getViewModelStore()
реализации, тогда мы найдем ответ.
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
Деятельность делает это с помощью чего-то под названием NonConfigurationInstances
. NonConfigurationInstances
является окончательным c конечным классом
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
Таким образом, он сначала проверяет, есть ли уже viewmodelstore
, сохраненный в NonConfigurationInstances
, если нет, он создает новый ViewModelStore
или возвращает существующий ViewModelStore
.
Тогда почему ViewModel
не выживет из-за недостатка памяти или finish()
Scenar ios?
ViewModelStore
имеет метод clear()
:
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
Таким образом, этот метод clear()
вызывается в onDestroy()
действия или фрагмента, который очищает HashMap
, за исключением изменений конфигурации. Вот код:
if (mViewModelStore != null && !isChangingConfigurations) {
mViewModelStore.clear();
}
Теперь вы знаете секретный рецепт того, как ViewModel выживает после изменения конфигурации.
Счастливое кодирование ...
ВАЖНО : Я не верю, чтобы брать кредиты на чужую работу. Чтобы сделать его легко доступным в стеке переполнение Я скопировал все из статьи Интересный случай Android ViewModel