我正在尝试在我的应用中使用ViewModel。我想到的问题是, View 模型如何在配置更改中生存下来。我读了许多博客文章,内容是:



但我尝试对此进行更多探索,发现在支持库27.1.0+ 中,他们已删除了HolderFragment,并带有Description字样



现在的问题是,他们现在如何做同样的事情?

最佳答案

ViewModelProviders.of()方法创建的ViewModel存储在ViewModelStore哈希图中,因此真正的问题是ViewModelStore的存储方式。

对于 Activity ,此逻辑很简单。 ViewModelStore使用onRetainNonConfigurationInstance方法存储:

@Override
    @Nullable
    public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();

        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            // No one called getViewModelStore(), so see if there was an existing
            // ViewModelStore from our last NonConfigurationInstance
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }

        if (viewModelStore == null && custom == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }

对于 fragment ,情况要复杂一些。 FragmentManagerImpl现在有一个名为mNonConfig的字段:
private FragmentManagerViewModel mNonConfig;
它存储Fragment的UUID和ViewModelStore的哈希图。

mNonConfig字段是使用FragmentManagerImpl#attachController方法初始化的:
    public void attachController(@NonNull FragmentHostCallback host,
            @NonNull FragmentContainer container, @Nullable final Fragment parent) {
        if (mHost != null) throw new IllegalStateException("Already attached");
        mHost = host;
        mContainer = container;
        mParent = parent;
        if (mParent != null) {
            // Since the callback depends on us being the primary navigation fragment,
            // update our callback now that we have a parent so that we have the correct
            // state by default
            updateOnBackPressedCallbackEnabled();
        }
        // Set up the OnBackPressedCallback
        if (host instanceof OnBackPressedDispatcherOwner) {
            OnBackPressedDispatcherOwner dispatcherOwner = ((OnBackPressedDispatcherOwner) host);
            mOnBackPressedDispatcher = dispatcherOwner.getOnBackPressedDispatcher();
            LifecycleOwner owner = parent != null ? parent : dispatcherOwner;
            mOnBackPressedDispatcher.addCallback(owner, mOnBackPressedCallback);
        }

        // Get the FragmentManagerViewModel
        if (parent != null) {
            mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
        } else if (host instanceof ViewModelStoreOwner) {
            ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
            mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
        } else {
            mNonConfig = new FragmentManagerViewModel(false);
        }
    }

10-07 16:22