0

我有一个应用程序,它具有 Master/Detail 类型的架构。当我选择某个项目时,详细信息会显示在详细信息片段中。

为了让详细片段知道要加载什么,id通过Arguments. 在 VM 中使用SavedStateHandle,我可以直接从句柄中读取这些参数,而无需重新路由它Fragment本身。这对于第一个细节片段非常有用。问题来自下一个选择。

每次我加载详细信息时,id都会填充第一个选择,尽管每次创建一个新片段时都会与新的 ViewModel一起创建。

我正在研究生命周期视图模型保存状态库(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包含与 old 相同id的密钥,最后替换defaultState.

我可以理解这可能是真正恢复所需的行为,但在我的情况下,我没有恢复片段。是的,类是相同的,但我只是用另一个具有新/不同数据的细节片段替换细节片段。

难道我做错了什么?我可以给框架一个提示,这不是恢复并且我对旧片段中保存的值不感兴趣吗?

4

1 回答 1

0

我没有提到的是我正在使用ViewPager2主/详细视图。我不认为它对状态存留有一些影响,但它有。

ViewPager2库正在后台保存和恢复状态,然后由SavedStateHandle. 要使用状态映射片段,它使用来自FragmentStateAdapter. 我没有覆盖getItemId方法,所以 ID 是按位置分配的。

这当然会将相同的状态映射到确切位置上的新片段。实现getItemId将不同的 id 分配给片段的不同实例解决了这个问题。

于 2021-04-18T16:40:57.707 回答