First of all, how is the ViewModel instantiated

    protected open fun 
        getFragmentScopeViewModel(modelClass: Class<T>): T {
        if(! ::fragmentProvider.isInitialized) { fragmentProvider = ViewModelProvider(this)}return fragmentProvider.get(modelClass)
    }

    protected open fun 
        getActivityScopeViewModel(modelClass: Class<T>): T {
        if(! ::activityProvider.isInitialized) { activityProvider = ViewModelProvider(requireActivity()) }return activityProvider.get(modelClass)
    }
Copy the code

ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider: ViewModelProvider

How do I know? Look at the official answer. ViewModel: designed to store and manage data related to an interface in a life-cycle oriented manner. The ViewModel class lets the data persist after configuration changes such as screen rotation: ViewModelProvider: the ViewModel helper class that prepares the data for the interface. ViewModel objects are automatically retained during configuration changes so that the data they store is immediately available for use by the next activity or Fragment instance

Boy, it’s this pair, in life cycle fashion. What’s the difference

Activty vs. ViewModel lifecycle

Fight until Finish

Lifecycle is passed to the ViewModelProvider when the ViewModel is acquired. The ViewModel will remain in memory until Lifecycle is gone permanently: for an activity, when the activity completes; For fragments, this is when the fragment is separating

Okay, so how does the ViewModelProvider implement the construction

ViewModelProvider()

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        // Call another constructor secretly
        // 1. Create a ViewModelStore to store viewModels. 2. Create a Factory to instantiate the new ViewModel
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
}
Copy the code

ViewModelStore

This interface is used for activities, fragments, etc., to retrieve the ViewModelStore related to the current life cycleTake a look atComponentActivity.getViewModelStore():

    public ViewModelStore getViewModelStore(a) {
        if (getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        // fork is a singleton that implements ViewModelStore
        ensureViewModelStore();
        // Returns the ViewModelStore associated with this Activity
        returnmViewModelStore; } ` ` `void ensureViewModelStore(a) {
        if (mViewModelStore == null) {
            / / retrieve the previous by onRetainNonConfigurationInstance () returns the cache configuration after configuration changes
            NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
            // If the cache configuration is not empty, take the viewModelStore of the cache configuration
            if(nc ! =null) {
                mViewModelStore = nc.viewModelStore;
            }
            // If not, create an example
            if (mViewModelStore == null) {
                mViewModelStore = newViewModelStore(); }}}Copy the code

The ViewModelStore is used to store viewModels in a HashMap.

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(a) {
        return new HashSet<>(mMap.keySet());
    }

    public final void clear(a) {
        for(ViewModel vm : mMap.values()) { vm.clear(); } mMap.clear(); }}Copy the code

ViewModelProviderFactory

The back of the same Activity, fragments and also realizes the HasDefaultViewModelProviderFactory interface, realize oneself create ViewModel ViewModelProviderFactory, see figureTake a look atComponentActivity.getViewModelStore():

    public ViewModelProvider.Factory getDefaultViewModelProviderFactory(a) {
        if (getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        // It's as simple as that, direct instantiation
        if (mDefaultFactory == null) {
            mDefaultFactory = new SavedStateViewModelFactory(
                    getApplication(),
                    this, getIntent() ! =null ? getIntent().getExtras() : null);
        }
        return mDefaultFactory;
    }
Copy the code

A little things, like this instance SavedStateViewModelFactory, see how specific the get ()

    // Step 1: get
    public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        // If the class is local or anonymous, it will crash
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        // Hey, keep getting
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    // Step 2: get
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);
        // Check whether there is a cache
        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        }
        // Then, if null, instantiate the ViewModel through the concrete factory class
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        // Put it in cache
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    } 
    // Instantiate the ViewModel
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
        // Use reflection to find the current ViewModel constructor
        if(isAndroidViewModel && mApplication ! =null) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        if (constructor == null) {
            return mFactory.create(modelClass);
        }
        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        // call the constructor to instantiate
        try {
            T viewmodel;
            if(isAndroidViewModel && mApplication ! =null) {
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to access " + modelClass, e);
        } catch (InstantiationException e) {
            throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("An exception happened in constructor of "+ modelClass, e.getCause()); }}Copy the code

The architectural role of the ViewModel

Salute to the official, do not understand the gold content of this map, do not understand MMVM