【发布时间】:2021-07-11 20:30:40
【问题描述】:
我有一个应用程序,它具有 Master/Detail 类型的架构。当我选择某个项目时,详细信息会显示在详细信息片段中。
要知道要加载什么的详细信息片段id 是通过Arguments 发送的。在 VM 中使用 SavedStateHandle 我可以直接从句柄中读取这些参数,而无需在 Fragment 本身中重新路由它。这对于第一个细节片段非常有用。问题出现在下一个选择中。
每次我加载详细信息时,都会填充第一次选择的id,尽管每次创建新片段以及新视图模型。
我正在查看生命周期视图模型保存状态库的代码 (v.2.3.1) 并在 SavedStateHandle 中找到了这个方法调用:
static SavedStateHandle createHandle(@Nullable Bundle restoredState,
@Nullable Bundle defaultState) {
if (restoredState == null && defaultState == null) {
return new SavedStateHandle();
}
Map<String, Object> state = new HashMap<>();
if (defaultState != null) {
for (String key : defaultState.keySet()) {
state.put(key, defaultState.get(key));
}
}
if (restoredState == null) {
return new SavedStateHandle(state);
}
ArrayList keys = restoredState.getParcelableArrayList(KEYS);
ArrayList values = restoredState.getParcelableArrayList(VALUES);
if (keys == null || values == null || keys.size() != values.size()) {
throw new IllegalStateException("Invalid bundle passed as restored state");
}
for (int i = 0; i < keys.size(); i++) {
state.put((String) keys.get(i), values.get(i));
}
return new SavedStateHandle(state);
}
在这里我可以看到defaultState 为每个新视图模型设置了正确的 id。但正如您所见,defaultState 首先处理,restoredState 然后处理。 restoredState 包含 与旧的 id 相同的密钥,最后替换来自 defaultState 的正确密钥。
我可以理解这可能是真正恢复所需的行为,但在我的情况下,我没有恢复片段。是的,类是相同的,但我只是用另一个具有新/不同数据的细节片段替换细节片段。
我做错了吗?我可以给框架一个提示,这不是恢复并且我对旧片段中保存的值不感兴趣吗?
【问题讨论】:
-
如果您正在创建一个全新的片段并因此获得一个新的 ViewModel,那么
restoredState将为空。是什么让您认为它不为空? -
调试?我可以看到它不为空。根据定义, saveInstanceState 应该在实例之间保存状态,所以我并不感到惊讶。但在这种情况下,这并不是真正需要的行为。
-
一个全新的 Fragment 和一个 ViewModel 关联的工作一个全新的 Fragment 没有保存状态。请包括您如何创建全新的 Fragment 以及如何创建 ViewModel
-
确定是什么原因造成的!感谢您指出 Fragment 创建,深入研究我找到了罪魁祸首。查看答案。
标签: android android-fragments android-lifecycle android-savedstate viewmodel-savedstate