Android ViewModel 如何确保它必须绑定相同的 Activity 或 Fragment(在屏幕旋转的情况下)?
How Android ViewModel insures that, it has to bind with the same Activity or Fragment(in case of Screen Rotation)?
我现在正在研究 Android ViewModel。一个问题一直在我脑海中浮现。尽管我们正在 onCreate 或 onCreateView 中创建新对象,ViewModel 如何确保在屏幕旋转后重新绑定相同的 Activity 或 Fragment?
有没有人对此有正确的答案,请告诉我。我试图在这么多教程中找到解决方案。
提前致谢!
创建 ViewModelProvider
的新实例时,第一个参数是 activity.getViewModelStore()
,根据文档,
Returns the {@link ViewModelStore} associated with this activity
Overriding this method is no longer supported and this method will be made
final
in a future version of ComponentActivity.
@return a {@code ViewModelStore}
@throws IllegalStateException if called before the Activity is attached to the Application
instance i.e., before onCreate()
它 returns 一个 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();
}
}
基本上,它是一个 class,它有一个 HashMap
,其键是 DEFAULT_KEY + “:” + canonicalName
,其中 DEFAULT_KEY
是 androidx.lifecycle.ViewModelProvider.DefaultKey
,值是 ViewModel
这意味着每个 activity 和片段都有一个 ViewModelStore
,它将所有声明的 ViewModels
分别保留在 activity 或片段中。
但是 ViewModelStore
如何在方向改变后幸存下来?
在ViewModelStore
的文档中定义
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}.
因此活动有责任在方向更改期间保留 ViewModelStore
。
如果我们回到 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();
}
}
activity 通过使用一种叫做 NonConfigurationInstances
的东西来做到这一点。 NonConfigurationInstances
是静态最终 class
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
所以它首先检查是否已经有一个 viewmodelstore
存储在 NonConfigurationInstances
如果没有它创建一个新的 ViewModelStore
或 returns 现有的 ViewModelStore
.
那为什么 ViewModel
不能在低内存或 finish()
情况下生存?
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()
方法在 activity 的 onDestroy()
或清除 HashMap
的片段中被调用,除了在配置更改期间。这是代码:
if (mViewModelStore != null && !isChangingConfigurations) {
mViewModelStore.clear();
}
现在您知道了 ViewModel 如何在配置更改后幸存下来的秘诀。
编码愉快…
重要提示:我不相信将别人的工作归功于他人。为了使其在堆栈 overflow 上易于使用,我复制粘贴了文章 The curious case of Android ViewModel
中的所有内容
我现在正在研究 Android ViewModel。一个问题一直在我脑海中浮现。尽管我们正在 onCreate 或 onCreateView 中创建新对象,ViewModel 如何确保在屏幕旋转后重新绑定相同的 Activity 或 Fragment?
有没有人对此有正确的答案,请告诉我。我试图在这么多教程中找到解决方案。
提前致谢!
创建 ViewModelProvider
的新实例时,第一个参数是 activity.getViewModelStore()
,根据文档,
Returns the {@link ViewModelStore} associated with this activity
Overriding this method is no longer supported and this method will be made
final
in a future version of ComponentActivity. @return a {@code ViewModelStore} @throws IllegalStateException if called before the Activity is attached to the Application instance i.e., before onCreate()
它 returns 一个 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();
}
}
基本上,它是一个 class,它有一个 HashMap
,其键是 DEFAULT_KEY + “:” + canonicalName
,其中 DEFAULT_KEY
是 androidx.lifecycle.ViewModelProvider.DefaultKey
,值是 ViewModel
这意味着每个 activity 和片段都有一个 ViewModelStore
,它将所有声明的 ViewModels
分别保留在 activity 或片段中。
但是 ViewModelStore
如何在方向改变后幸存下来?
在ViewModelStore
的文档中定义
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}.
因此活动有责任在方向更改期间保留 ViewModelStore
。
如果我们回到 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();
}
}
activity 通过使用一种叫做 NonConfigurationInstances
的东西来做到这一点。 NonConfigurationInstances
是静态最终 class
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
所以它首先检查是否已经有一个 viewmodelstore
存储在 NonConfigurationInstances
如果没有它创建一个新的 ViewModelStore
或 returns 现有的 ViewModelStore
.
那为什么 ViewModel
不能在低内存或 finish()
情况下生存?
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()
方法在 activity 的 onDestroy()
或清除 HashMap
的片段中被调用,除了在配置更改期间。这是代码:
if (mViewModelStore != null && !isChangingConfigurations) {
mViewModelStore.clear();
}
现在您知道了 ViewModel 如何在配置更改后幸存下来的秘诀。
编码愉快…
重要提示:我不相信将别人的工作归功于他人。为了使其在堆栈 overflow 上易于使用,我复制粘贴了文章 The curious case of Android ViewModel
中的所有内容