美文网首页
Jetpack-ViewModel源码解析

Jetpack-ViewModel源码解析

作者: 张荣旗 | 来源:发表于2021-12-30 10:33 被阅读0次

    ViewModel源码解析

    源码版本:

    • ViewModel:2.4.0
    • Android:31
    • androidx.activity:activity:1.4.0
    • androidx.fragment:fragment:1.4.0

    需会使用:Lifecycle

    导航:

    使用

    声明ViewModel

    class MyViewModel : ViewModel() {
    
        override fun onCleared() {
            super.onCleared()
        }
    }
    

    获取ViewModel

    class MyActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            // 获取ViewModel
            val model = ViewModelProvider(this).get(MyViewModel::class.java)
            // observe
            model.getUsers().observe(this, Observer<List<User>>{ users ->
                // update UI
            })
        }
    }
    

    ViewModel生命周期

    enter image description here

    源码

    声明ViewModel

    ViewModel类

    public abstract class ViewModel {
        // 标签集合
        @Nullable
        private final Map<String, Object> mBagOfTags = new HashMap<>();
        // 标记是否是已清除
        private volatile boolean mCleared = false;
    
        // 当ViewModel被清除时调用
        protected void onCleared() {
        }
    
        @MainThread
        final void clear() {
            mCleared = true;
            if (mBagOfTags != null) {
                synchronized (mBagOfTags) {
                    for (Object value : mBagOfTags.values()) {
                        // see comment for the similar call in setTagIfAbsent
                        closeWithRuntimeException(value);
                    }
                }
            }
            onCleared();
        }
    
        // 添加数据key、value,如果key的值已经存在,则返回已存在的值,否则添加新的值。
        // 并判断如果ViewModel是已被清除的,则返回的值如果是Closeable,就会调用close方法释放。即ViewModel已经被清除,再添加新的,则也会释放。
        @SuppressWarnings("unchecked")
        <T> T setTagIfAbsent(String key, T newValue) {
            T previous;
            synchronized (mBagOfTags) {
                previous = (T) mBagOfTags.get(key);
                if (previous == null) {
                    mBagOfTags.put(key, newValue);
                }
            }
            T result = previous == null ? newValue : previous;
            if (mCleared) {
    
                closeWithRuntimeException(result);
            }
            return result;
        }
    
        // 获取被添加的数据
        <T> T getTag(String key) {
            if (mBagOfTags == null) {
                return null;
            }
            synchronized (mBagOfTags) {
                return (T) mBagOfTags.get(key);
            }
        }
    
        private static void closeWithRuntimeException(Object obj) {
            if (obj instanceof Closeable) {
                // 是Closeable子类,则调用close关闭。
                try {
                    ((Closeable) obj).close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    

    ViewModel被清除的时候,会清空Tag并调用onCleared方法通知ViewModel被清除。

    获取ViewModel

    使用

    class MyActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            // 获取ViewModel
            val model = ViewModelProvider(this).get(MyViewModel::class.java)
            // observe
            model.getUsers().observe(this, Observer<List<User>>{ users ->
                // update UI
            })
        }
    }
    

    获取ViewModel,首先需要创建ViewModelProvider,然后再调用其get方法获取,我们先来看一下ViewModelProvider对象是如果创建的,然后再看get方法是如果获取的。

    ViewModelProvider构造方法

    ViewModelProvider构造方法

    public open class ViewModelProvider(
        private val store: ViewModelStore,
        private val factory: Factory
    ) {
        public constructor(
            owner: ViewModelStoreOwner
        ) : this(owner.viewModelStore, defaultFactory(owner))
    
        
        public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
            owner.viewModelStore,
            factory
        )  
    }
    

    ViewModelProviderViewModel提供者,创建它需要ViewModelStoreViewModelProvider.Factory,而ViewModelStore又可以从ViewModelStoreOwner中获取,我们分别来看下这几个类。

    ViewModelStore

    ViewModelStore类

    public class ViewModelStore {
    
        // ViewModel集合
        private final HashMap<String, ViewModel> mMap = new HashMap<>();
    TestViewModel
        // 保存ViewModel,如果key已经存在,则值进行覆盖,之前的ViewModel则调用onCleared清空逻辑。
        final void put(String key, ViewModel viewModel) {
            ViewModel oldViewModel = mMap.put(key, viewModel);
            if (oldViewModel != null) {
                oldViewModel.onCleared();
            }
        }
    
        // 获取ViewModel
        final ViewModel get(String key) {
            return mMap.get(key);
        }
    
        // 获取所有的key
        Set<String> keys() {
            return new HashSet<>(mMap.keySet());
        }
    
        // 清除内部存储并通知ViewModels它们不再使用。
        public final void clear() {
            for (ViewModel vm : mMap.values()) {
                vm.clear();
            }
            mMap.clear();
        }
    }
    

    ViewModelProviderViewModel商店,它是用来存储获取ViewModel的,是使用HashMap来实现的。其clear方法会清除内部存储并通知ViewModels它们不再使用。

    ViewModelStoreOwner

    ViewModelStoreOwner类

    public interface ViewModelStoreOwner {
    
        @NonNull
        ViewModelStore getViewModelStore();
    }
    

    ViewModelStoreOwnerViewModelStore的持有者,通过它的子类可以获取到ViewModelStoreandroidxActivityFragment都已经实现了ViewModelStoreOwner,我们分别看一下具体实现。

    Activity

    androidx.activity.ComponentActivity类

    public class ComponentActivity extends androidx.core.app.ComponentActivity implements
            ContextAware,
            LifecycleOwner,
            ViewModelStoreOwner,
            HasDefaultViewModelProviderFactory,
            SavedStateRegistryOwner,
            OnBackPressedDispatcherOwner,
            ActivityResultRegistryOwner,
            ActivityResultCaller {
            
        private ViewModelStore mViewModelStore;
        
        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            if (getApplication() == null) {
                // 不能在onCreate调用之前获取ViewModel
                throw new IllegalStateException("Your activity is not yet attached to the "
                        + "Application instance. You can't request ViewModel before onCreate call.");
            }
            // 确保ViewModelStore
            ensureViewModelStore();
            // 返回ViewModelStore
            return mViewModelStore;
        }
        
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        void ensureViewModelStore() {
            if (mViewModelStore == null) {
                NonConfigurationInstances nc =
                        (NonConfigurationInstances) getLastNonConfigurationInstance();
                if (nc != null) {
                    // 从 NonConfigurationInstances 中恢复ViewModelStore
                    mViewModelStore = nc.viewModelStore;
                }
                if (mViewModelStore == null) {
                    // mViewModelStore为空,则创建。
                    mViewModelStore = new ViewModelStore();
                }
            }
        }
        
    }
    

    androidx Activity获取ViewModelStore,先从 NonConfigurationInstances 中恢复ViewModelStore(确保Activity重建后还能获取到之前的ViewModelStore,具体分析看下面ViewModel是如何保持不变的?),如果还是没有,则进行创建。

    说明:

    1. androidx Activity不能在onCreate调用之前获取ViewModel

    Fragment

    androidx.fragment.app.Fragment类

    public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
            ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
            ActivityResultCaller {
            
        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            if (mFragmentManager == null) {
                // 不能从detached的Fragment访问ViewModels
                throw new IllegalStateException("Can't access ViewModels from detached fragment");
            }
            if (getMinimumMaxLifecycleState() == Lifecycle.State.INITIALIZED.ordinal()) {
                // 当使用setMaxLifecycle(INITIALIZED)时,不支持在Fragment到达onCreate()之前调用getViewModelStore()
                throw new IllegalStateException("Calling getViewModelStore() before a Fragment "
                        + "reaches onCreate() when using setMaxLifecycle(INITIALIZED) is not "
                        + "supported");
            }
            return mFragmentManager.getViewModelStore(this);
        }
    }
    

    FragmentManager --> getViewModelStore方法

    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
        return mNonConfig.getViewModelStore(f);
    }
    

    FragmentManagerViewModel --> getViewModelStore方法

    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
        ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
        if (viewModelStore == null) {
            viewModelStore = new ViewModelStore();
            mViewModelStores.put(f.mWho, viewModelStore);
        }
        return viewModelStore;
    }
    

    androidx Fragment获取ViewModelStore,先获取到 FragmentManagerViewModel(确保Fragment重建后还能获取到之前的ViewModelStore,具体分析看下面ViewModel是如何保持不变的?),然后再从其mViewModelStores中获取,如果没有,则进行创建。

    说明:

    1. androidx Fragment不能在onDetach调用之后获取ViewModel

    ViewModelProvider.Factory

    ViewModelProvider.Factory类

    public interface Factory {
    
        // 创建给定ViewModel Class的新实例。
        @NonNull
        <T extends ViewModel> T create(@NonNull Class<T> modelClass);
    }
    

    ViewModelProvider.FactoryViewModel的创建工厂,此Factory通过ViewModel类的class,创建ViewModel实例。我们分别来看一下它的子类KeyedFactoryNewInstanceFactoryAndroidViewModelFactory

    ViewModelProvider.KeyedFactory

    ViewModelProvider.KeyedFactory类

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    public abstract class KeyedFactory : OnRequeryFactory(), Factory {
    
        public abstract fun <T : ViewModel> create(
            key: String,
            modelClass: Class<T>
        ): T
    
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            throw UnsupportedOperationException(
                "create(String, Class<?>) must be called on implementations of KeyedFactory"
            )
        }
    }
    

    KeyedFactoryFactory 的抽象子类,重写了create(Class<?>)方法,并且KeyedFactory子类必须重写create( Class<?>)方法并应该调用其create(String, Class<?>)方法。

    ViewModelProvider.NewInstanceFactory

    ViewModelProvider.NewInstanceFactory类

    public open class NewInstanceFactory : Factory {
        @Suppress("DocumentExceptions")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return try {
                // 通过反射获取实例
                modelClass.newInstance()
            } catch (e: InstantiationException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            } catch (e: IllegalAccessException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            }
        }
    
        public companion object {
            private var sInstance: NewInstanceFactory? = null
    
            // 单例 NewInstanceFactory
            @JvmStatic
            public val instance: NewInstanceFactory
                @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
                get() {
                    if (sInstance == null) {
                        sInstance = NewInstanceFactory()
                    }
                    return sInstance!!
                }
        }
    }
    

    NewInstanceFactoryFactory 的子类,实现了create(Class<?>)方法,通过ViewModel类的class无参反射创建ViewModel实例。

    说明:

    1. 使用NewInstanceFactory创建,此ViewModel必须有无参的且不是私有的构造方法。
    • 可以处理如下ViewModel
      • class MyViewModel : ViewModel()
    1. NewInstanceFactory.instance为全局单例NewInstanceFactory,防止了每次创建工厂,优化了性能。

    ViewModelProvider.AndroidViewModelFactory

    ViewModelProvider.AndroidViewModelFactory类

    public open class AndroidViewModelFactory(
        private val application: Application
    ) : NewInstanceFactory() {
        @Suppress("DocumentExceptions")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
                try {
                    // 此ViewModel为AndroidViewModel的子类,则传入Application并创建。
                    modelClass.getConstructor(Application::class.java).newInstance(application)
                } catch (e: NoSuchMethodException) {
                    throw RuntimeException("Cannot create an instance of $modelClass", e)
                } catch (e: IllegalAccessException) {
                    throw RuntimeException("Cannot create an instance of $modelClass", e)
                } catch (e: InstantiationException) {
                    throw RuntimeException("Cannot create an instance of $modelClass", e)
                } catch (e: InvocationTargetException) {
                    throw RuntimeException("Cannot create an instance of $modelClass", e)
                }
            } else super.create(modelClass) // 否则,则执行父类的反射创建。
        }
    
        public companion object {
            // 获取默认工厂,如果owner有默认工厂则用owner的,否则用NewInstanceFactory工厂(反射创建)。
            internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =
                if (owner is HasDefaultViewModelProviderFactory)
                    owner.defaultViewModelProviderFactory else instance
    
            // 获取的默认Key
            internal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"
    
            private var sInstance: AndroidViewModelFactory? = null
            
            // 单例 AndroidViewModelFactory
            @JvmStatic
            public fun getInstance(application: Application): AndroidViewModelFactory {
                if (sInstance == null) {
                    sInstance = AndroidViewModelFactory(application)
                }
                return sInstance!!
            }
        }
    }
    

    AndroidViewModelFactoryNewInstanceFactory 的子类,重写了create(Class<?>)方法,通过ViewModel类的class判断,如果此ViewModelAndroidViewModel的子类,则传入Application反射创建,否则走父类逻辑无参反射创建ViewModel实例。

    说明:

    1. 使用AndroidViewModelFactory创建,如果此ViewModelAndroidViewModel子类,必须有一参的且是Application不是私有的构造方法(不能无参);否则必须有无参的且不是私有的构造方法(不能有参)。
    • 可以处理如下ViewModel
      • class MyViewModel : ViewModel()
      • class MyViewModel(application: Application) : AndroidViewModel(application)
    1. AndroidViewModelFactory.getInstance为全局单例AndroidViewModelFactory,防止了每次创建工厂,优化了性能。

    defaultFactory方法为获取默认工厂,如果ViewModelStoreOwner子类也实现了HasDefaultViewModelProviderFactory,则用其提供的工厂,否则用NewInstanceFactory工厂(创建无参ViewModel)。

    HasDefaultViewModelProviderFactory

    HasDefaultViewModelProviderFactory类

    public interface HasDefaultViewModelProviderFactory {
        
        // 获取默认Factory
        @NonNull
        ViewModelProvider.Factory getDefaultViewModelProviderFactory();
    }
    

    HasDefaultViewModelProviderFactory为标记可以获取到默认FactoryandroidxActivityFragment都已经实现了HasDefaultViewModelProviderFactory,我们来分别看一下它们的具体实现。

    Activity

    androidx.activity.ComponentActivity类

    public class ComponentActivity extends androidx.core.app.ComponentActivity implements
            ContextAware,
            LifecycleOwner,
            ViewModelStoreOwner,
            HasDefaultViewModelProviderFactory,
            SavedStateRegistryOwner,
            OnBackPressedDispatcherOwner,
            ActivityResultRegistryOwner,
            ActivityResultCaller {
            
        private ViewModelProvider.Factory mDefaultFactory;
        
        @NonNull
        @Override
        public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
            if (getApplication() == null) {
                // 不能在onCreate调用之前获取ViewModel
                throw new IllegalStateException("Your activity is not yet attached to the "
                        + "Application instance. You can't request ViewModel before onCreate call.");
            }
            if (mDefaultFactory == null) {
                // 默认工厂为空,则进行创建SavedStateViewModelFactory,会把Application、当前页面传入的参数,传入到构造方法中。
                mDefaultFactory = new SavedStateViewModelFactory(
                        getApplication(),
                        this,
                        getIntent() != null ? getIntent().getExtras() : null);
            }
            return mDefaultFactory;
        }
        
    }
    

    Fragment

    androidx.fragment.app.Fragment类

    public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
            ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
            ActivityResultCaller {
            
        ViewModelProvider.Factory mDefaultFactory;
    
        @NonNull
        @Override
        public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
            if (mFragmentManager == null) {
                   // 不能从detached的Fragment访问ViewModels
                throw new IllegalStateException("Can't access ViewModels from detached fragment");
            }
            if (mDefaultFactory == null) {
                 // 默认工厂为空,则进行创建SavedStateViewModelFactory,会把Application、当前页面传入的参数,传入到构造方法中。
                Application application = null;
                Context appContext = requireContext().getApplicationContext();
                while (appContext instanceof ContextWrapper) {
                    if (appContext instanceof Application) {
                        application = (Application) appContext;
                        break;
                    }
                    appContext = ((ContextWrapper) appContext).getBaseContext();
                }
                if (application == null && FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                    Log.d(FragmentManager.TAG, "Could not find Application instance from "
                            + "Context " + requireContext().getApplicationContext() + ", you will "
                            + "not be able to use AndroidViewModel with the default "
                            + "ViewModelProvider.Factory");
                }
                // 创建SavedStateViewModelFactory
                mDefaultFactory = new SavedStateViewModelFactory(
                        application,
                        this,
                        getArguments());
            }
            return mDefaultFactory;
        }
    }
    

    androidxActivityFragment的实现相同,都是创建SavedStateViewModelFactory并会把Application、当前页面传入的参数,传入到构造方法中,我们来看一下SavedStateViewModelFactory

    SavedStateViewModelFactory

    SavedStateViewModelFactory类

    public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
        private final Application mApplication;
        private final ViewModelProvider.Factory mFactory;
        private final Bundle mDefaultArgs;
        private final Lifecycle mLifecycle;
        private final SavedStateRegistry mSavedStateRegistry;
    
        // 构造方法,未传默认参数
        public SavedStateViewModelFactory(@Nullable  Application application,
                @NonNull SavedStateRegistryOwner owner) {
            this(application, owner, null);
        }
        
        // 构造方法,传了默认参数
        @SuppressLint("LambdaLast")
        public SavedStateViewModelFactory(@Nullable Application application,
                @NonNull SavedStateRegistryOwner owner,
                @Nullable Bundle defaultArgs) {
            mSavedStateRegistry = owner.getSavedStateRegistry();
            mLifecycle = owner.getLifecycle();
            mDefaultArgs = defaultArgs;
            mApplication = application;
            mFactory = application != null
                    ? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
                    : ViewModelProvider.NewInstanceFactory.getInstance();
        }
    
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
            // 是否是AndroidViewModel子类
            boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
            Constructor<T> constructor;
            if (isAndroidViewModel && mApplication != null) {
                // 是AndroidViewModel子类,获取(Application, SavedStateHandle)签名的构造方法
                constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
            } else {
                // 不是AndroidViewModel子类,获取(SavedStateHandle)签名的构造方法
                constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
            }
    
            if (constructor == null) {
                // 没有获取到,则说明是没用SavedStateHandle的构造方法,则直接用mFactory处理。
                return mFactory.create(modelClass);
            }
    
            // 以下为需要SavedStateHandle
            SavedStateHandleController controller = SavedStateHandleController.create(
                    mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
            try {
                T viewmodel;
                if (isAndroidViewModel && mApplication != null) {
                    // 反射创建(Application, SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
                    viewmodel = constructor.newInstance(mApplication, controller.getHandle());
                } else {
                    // 反射创建(SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
                    viewmodel = constructor.newInstance(controller.getHandle());
                }
                viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
                // 返回ViewModel
                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());
            }
        }
    
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            String canonicalName = modelClass.getCanonicalName();
            if (canonicalName == null) {
                throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
            }
            // 使用类名作为key,创建ViewModemLastNonConfigurationInstancesl。
            return create(canonicalName, modelClass);
        }
        
        // (Application, SavedStateHandle)签名
        private static final Class<?>[] ANDROID_VIEWMODEL_SIGNATURE = new Class[]{Application.class,
                SavedStateHandle.class};
        // (SavedStateHandle)签名
        private static final Class<?>[] VIEWMODEL_SIGNATURE = new Class[]{SavedStateHandle.class};
    
        // 找到对应签名的构造方法,没有返回null。
        @SuppressWarnings("unchecked")
        private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
                Class<?>[] signature) {
            for (Constructor<?> constructor : modelClass.getConstructors()) {
                Class<?>[] parameterTypes = constructor.getParameterTypes();
                if (Arrays.equals(signature, parameterTypes)) {
                    return (Constructor<T>) constructor;
                }
            }
            return null;
        }
    
        /**
         * @hide
         */
        @Override
        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
        public void onRequery(@NonNull ViewModel viewModel) {
            attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
        }
    }
    
    

    androidxActivityFragment创建默认工厂的代码流程:

    1. androidxActivityFragment创建SavedStateViewModelFactory时,都传入了Application,所以其工厂mFactoryAndroidViewModelFactory
    2. create(String,Class<*>)方法,如果ViewModel构造方法里面没有用SavedStateHandle,则直接使用工厂mFactory(为AndroidViewModelFactory)进行创建。

    说明:

    1. 使用SavedStateViewModelFactory创建,如果此ViewModel构造方法里面没有用SavedStateHandle,则直接使用AndroidViewModelFactory创建;如果使用了,则反射创建(Application, SavedStateHandle)(SavedStateHandle)签名的构造方法。
    • 可以处理如下ViewModel
      • class MyViewModel : ViewModel()
      • class MyViewModel(application: Application) : AndroidViewModel(application)
      • class MyViewModel(val handle: SavedStateHandle) : ViewModel()
      • class MyViewModel(application: Application, val handle: SavedStateHandle) : AndroidViewModel(application)
    1. 由于SavedStateHandle的创建,传入了当前页面传入的参数,所以通过SavedStateHandle也能获取到当前页面传入的参数
    2. 使用SavedStateHandle相关的,将在Jetpact-保存状态讲解。

    说完了ViewModelProvider对象的创建,我们再来看看其get()方法是如果获取ViewModel的。

    ViewModelProvider.get方法

    ViewModelProvider--> get方法

    @MainThread
    public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
        // 获取类名
        val canonicalName = modelClass.canonicalName
            ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
        // 使用默认名+类名作为key,获取ViewModel。
        return get("$DEFAULT_KEY:$canonicalName", modelClass)
    }
    
    @Suppress("UNCHECKED_CAST")
    @MainThread
    public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
        // 从ViewModelStore中获取ViewModel
        var viewModel = store[key]
        if (modelClass.isInstance(viewModel)) {
            // viewModel不为空,并且是目标类,直接返回。
            (factory as? OnRequeryFactory)?.onRequery(viewModel)
            return viewModel as T
        } else {
            @Suppress("ControlFlowWithEmptyBody")
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        // 没有找到ViewModel,则直接创建,并存入到ViewModelStore中。
        viewModel = if (factory is KeyedFactory) {
            // 是KeyedFactory的子类直接调用create(key, modelClass)方法。
            factory.create(key, modelClass)
        } else {
            factory.create(modelClass)
        }
        // 存入到ViewModelStore中
        store.put(key, viewModel)
        return viewModel
    }
    

    ViewModelProvider.get代码流程:

    1. get(Class<*>)方法,使用默认名+类名作为key,调用get(String, Class<*>)方法,获取ViewModel
    2. get(String, Class<*>)方法,先从ViewModelStore中获取ViewModel,如果有并且是目标类,则直接返回,否则使用Factory直接创建,并存入到ViewModelStore中,以便后续获取。

    总结

    以在androidxActivity内获取无参构造方法ViewModel为例,讲解代码流程。

    声明ViewModel

    class MyViewModel : ViewModel() {
    
        override fun onCleared() {
            super.onCleared()
        }
    }
    

    获取ViewModel

    class MyActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            // 获取ViewModel
            val model = ViewModelProvider(this).get(MyViewModel::class.java)      
        }
    }
    

    示例代码流程:

    1. 创建ViewModelProvider,传入的是ComponentActivity,它的ViewModelStoreComponentActivity提供的ViewModelStore,它的FactoryComponentActivity提供的默认工厂SavedStateViewModelFactory
    2. get()方法,先从ViewModelStore中获取ViewModel,如果有并且是目标类,则直接返回,否则使用FactorySavedStateViewModelFactory)直接创建,并存入到ViewModelStore中,以便后续获取。
    3. SavedStateViewModelFactorycreate()方法,会直接调用AndroidViewModelFactorycreate()方法。(因为获取的MyViewModel未使用SavedStateHandle,所以会直接调用mFactory的创建。又因为创建SavedStateViewModelFactory时传入了Application,所以mFactoryAndroidViewModelFactory
    4. AndroidViewModelFactorycreate()方法,会直接使用反射创建无参构造方法。(因为获取的MyViewModel未继承AndroidViewModel,所以会走父类NewInstanceFactory的逻辑创建)

    ViewModel生命周期

    ViewModel生命周期为什么会比ActivityFragment的生命周期长,它是如何保持不变的,以及它是如何被清除的,我们来分别分析以下。

    ViewModel是如何保持不变的?

    ActivityFragment配置变更(如:屏幕旋转)的情况会销毁重新创建,但是再次获取的ViewModel实例不变。反向分析其原因,要想要ViewModel实例不变,则需要保持ViewModelStore不变。我们分别看一下androidxActivityFragmentgetViewModelStore()方法。

    Activity

    ComponentActivity--> getViewModelStore方法

    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        if (getApplication() == null) {
            // 不能在onCreate调用之前获取ViewModel
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        // 确保ViewModelStore
        ensureViewModelStore();
        // 返回ViewModelStore
        return mViewModelStore;
    }
    
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void ensureViewModelStore() {
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // 从 NonConfigurationInstances 中恢复ViewModelStore
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                // mViewModelStore为空,则创建。
                mViewModelStore = new ViewModelStore();
            }
        }
    }
    

    获取ViewModelStore,我们先从NonConfigurationInstances中获取,其内部包含了一个ViewModelStore成员变量,我们先来分析一下NonConfigurationInstances.viewModelStore是如何被赋值的,然后再来分析又是如何获取到它的。

    说明:

    1. 为什么ComponentActivitymViewModelStore属性,在配置变更之前存入值,而在配置变更之后为空?
    • 因为Activity配置变更之后,重新创建的ActivityActivity对象为新的,所以其mViewModelStore属性为初始状态:空。

    ComponentActivity.NonConfigurationInstances类

    static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }
    

    通过查找引用,NonConfigurationInstances.viewModelStore是在ComponentActivityonRetainNonConfigurationInstance()方法里完成赋值的。

    ComponentActivity--> onRetainNonConfigurationInstance方法

    public final Object onRetainNonConfigurationInstance() {
        // Maintain backward compatibility.
        Object custom = onRetainCustomNonConfigurationInstance();
    
        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            // viewModelStore为空,则说明此时没有调用过getViewModelStore(),则通过getLastNonConfigurationInstance()从重建之前的获取。
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }
    
        if (viewModelStore == null && custom == null) {
            return null;
        }
    
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        // 记录当前viewModelStore,完成赋值操作。
        nci.viewModelStore = viewModelStore;
        return nci;
    }
    

    此方法,创建ComponentActivity.NonConfigurationInstances对象,记录当前viewModelStore,并返回此对象。

    说明:

    1. 重写了父类ActivityonRetainNonConfigurationInstance() 方法,使其创建的ComponentActivity.NonConfigurationInstances对象,在配置变更之后不受影响。
    2. ComponentActivity.NonConfigurationInstances.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore

    通过查找引用,ComponentActivity.onRetainNonConfigurationInstance()方法是在ActivityretainNonConfigurationInstances()方法里调用的。

    Activity--> retainNonConfigurationInstances方法

    NonConfigurationInstances retainNonConfigurationInstances() {
        // 获取到当前activity要保存的数据
        Object activity = onRetainNonConfigurationInstance();
        HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
    
        // We're already stopped but we've been asked to retain.
        // Our fragments are taken care of but we need to mark the loaders for retention.
        // In order to do this correctly we need to restart the loaders first before
        // handing them off to the next activity.
        mFragments.doLoaderStart();
        mFragments.doLoaderStop(true);
        ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
    
        if (activity == null && children == null && fragments == null && loaders == null
                && mVoiceInteractor == null) {
            return null;
            
        NonConfigurationInstances nci = new NonConfigurationInstances();
        // 记录当前activity数据,完成赋值操作。
        nci.activity = activity;
        nci.children = children;
        nci.fragments = fragments;
        nci.loaders = loaders;
        if (mVoiceInteractor != null) {
            mVoiceInteractor.retainInstance();
            nci.voiceInteractor = mVoiceInteractor;
        }
        return nci;
    }
    

    此方法,创建Activity.NonConfigurationInstances对象,记录其activity要保存数据(即ComponentActivity.NonConfigurationInstances对象),并返回此对象。

    说明:

    1. ActivityretainNonConfigurationInstances() 方法,使其创建的Activity.NonConfigurationInstances对象,在配置变更之后不受影响。
    2. Activity.NonConfigurationInstances.activity属性,保存了ComponentActivity.NonConfigurationInstances对象。

    通过全局搜索,Activity.retainNonConfigurationInstances()方法是在ActivityThreadperformDestroyActivity()方法里调用的。

    ActivityThread--> performDestroyActivity方法

    void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
        ...
        if (getNonConfigInstance) {
            try {
                // 从ActivityClientRecord的Activity中获取Activity.NonConfigurationInstances对象,
                // 然后保存到它的lastNonConfigurationInstances中,完成保存操作。
                r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException("Unable to retain activity "
                            + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
                }
            }
        }
        ...
            // 回调Activity的onDestroy方法
            mInstrumentation.callActivityOnDestroy(r.activity);
        ...
    }
    

    Activity执行销毁的时候,会先将不会因配置变更而改变的数据(即Activity.NonConfigurationInstances)保存到ActivityClientRecordlastNonConfigurationInstances属性中。

    说明:

    1. ActivityThread:它管理应用程序进程中主线程的执行、调度和执行activity、广播以及activity manager请求的其它操作。
    2. ActivityClientRecordActivity客户端记录,用于真实的Activity实例的簿记。
    3. ActivityClientRecord.lastNonConfigurationInstances.activity.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore

    接下来,我们来看一下是如果获取到保存了在配置变更之前维护的ViewModelStore的,我们先来看一下Activity.getLastNonConfigurationInstance()方法。

    Activity--> getLastNonConfigurationInstance方法

    @Nullable
    public Object getLastNonConfigurationInstance() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }
    

    mLastNonConfigurationInstancesActivity.NonConfigurationInstancesgetLastNonConfigurationInstance() 结果返回的是其activity属性,即ComponentActivity.NonConfigurationInstances对象。

    我们再来看一下,mLastNonConfigurationInstances是在哪里进行赋值的。通过查找,mLastNonConfigurationInstances是在Activityattach()里赋值的。

    Activity--> attach方法

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
            IBinder shareableActivityToken) {
        ...
        // 完成赋值操作
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        ...
    }
    

    通过全局搜索,Activity.retainNonConfigurationInstances()方法是在ActivityThreadperformDestroyActivity()方法里调用的。

    ActivityThread--> performLaunchActivity方法

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
                // 调用attach,传入ActivityClientRecord的lastNonConfigurationInstances。
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken, r.shareableActivityToken);
        ...
        return activity;
    }
    

    Activity执行启动的时候,会调用其attach()方法,传入ActivityClientRecord.lastNonConfigurationInstances保存的Activity.NonConfigurationInstances对象。

    说明:

    1. 为什么ActivityThreadperformLaunchActivity()performDestroyActivity()方法里面ActivityClientRecord是同一个?
    • 因为ActivityClientRecord保存在了ActivityThread.mActivities属性中,其为ActivityClientRecordMap集合,ActivityClientRecordstartActivityNow()方法内创建,并调用performLaunchActivity()方法,在其内部保存了创建的ActivityClientRecord对象,所以之后也能从Map中获取到之前存入的ActivityClientRecord,所以performLaunchActivity()performDestroyActivity()方法里面ActivityClientRecord是同一个。

    代码流程:

    1. ActivityThread.performDestroyActivity()方法,ActivityClientRecord.lastNonConfigurationInstances保存了Activity.retainNonConfigurationInstances()方法返回的Activity.NonConfigurationInstances对象。
    2. 其中的Activity.NonConfigurationInstances.activity属性,保存了ComponentActivity.onRetainNonConfigurationInstance()方法返回的ComponentActivity.NonConfigurationInstances对象。
    3. 其中的ComponentActivity.NonConfigurationInstances.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore
    4. ActivityThread.performLaunchActivity()方法,调用Activity.attach()方法,传入了保存在ActivityClientRecord.lastNonConfigurationInstancesActivity.NonConfigurationInstances对象。
    5. Activity.attach()方法,保存了传入的Activity.NonConfigurationInstances对象。
    6. 通过调用Activity.getLastNonConfigurationInstance()方法,即可拿到Activity.NonConfigurationInstances.activity属性保存的ComponentActivity.NonConfigurationInstances对象。
    7. 最后获取ComponentActivity.NonConfigurationInstances.viewModelStore属性的值,即可拿到ComponentActivityViewModelStore对象。

    总结:

    1. Activity销毁的时候,ActivityClientRecord.lastNonConfigurationInstances.activity.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore
    2. Activity启动的时候,ActivityClientRecord.lastNonConfigurationInstances的值在Activity.attach()的时候被存入到了Activity中,所以后续也能获取到在配置变更之前维护的ViewModelStore,所以配置变更前后获取到的ViewModelStoreViewModel实例不变

    Fragment

    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        if (mFragmentManager == null) {
        // 不能从detached的Fragment访问ViewModels
            throw new IllegalStateException("Can't access ViewModels from detached fragment");
        }
        if (getMinimumMaxLifecycleState() == Lifecycle.State.INITIALIZED.ordinal()) {
            throw new IllegalStateException("Calling getViewModelStore() before a Fragment "
                    + "reaches onCreate() when using setMaxLifecycle(INITIALIZED) is not "
                    + "supported");
        }
        return mFragmentManager.getViewModelStore(this);
    }
    

    mFragmentManagerFragmentManager,我们来看下其getViewModelStore()方法。

    FragmentManager --> getViewModelStore方法

    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
        return mNonConfig.getViewModelStore(f);
    }
    

    mNonConfigFragmentManagerViewModel,我们先来看一下它是如果创建的,然后再来看一下其getViewModelStore()方法。

    通过查找,发现其在FragmentManager.attachController()方法内创建。

    FragmentManager --> attachController方法

    @SuppressWarnings("deprecation")
    @SuppressLint("SyntheticAccessor")
    void attachController(@NonNull FragmentHostCallback<?> host,
            @NonNull FragmentContainer container, @Nullable final Fragment parent) {
        ...
        // Get the FragmentManagerViewModel
        if (parent != null) {
            // 当parent不为null时,调用父FragmentManager的getChildNonConfig获取。
            mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
        } else if (host instanceof ViewModelStoreOwner) {
            // 从host中获取ViewModelStore,然后使用FragmentManagerViewModel进行获取。
            ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
            mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
        } else {
            mNonConfig = new FragmentManagerViewModel(false);
        }
        ...
    }
    

    通过查找,发现attachController方法会在Fragmentattach的时候调用,其中hostFragmentActivity的内部类FragmentActivity.HostCallbacks,它实现了ViewModelStoreOwner接口。

    创建mNonConfig,如果没有父Fragment,则会从host中调用getViewModelStore()方法获取ViewModelStore,然后调用FragmentManagerViewModel.getInstance(viewModelStore)进行获取FragmentManagerViewModel

    因为一般没有父Fragment,大部分走第二个if,所以我们先来分析它,我们先来看一下FragmentActivity.HostCallbacksgetViewModelStore()方法,然后再来看一下FragmentManagerViewModelgetInstance()方法。

    FragmentActivity.HostCallbacks --> getViewModelStore方法

    class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
            ViewModelStoreOwner,
            OnBackPressedDispatcherOwner,
            ActivityResultRegistryOwner,
            SavedStateRegistryOwner,
            FragmentOnAttachListener {
        ...
        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            return FragmentActivity.this.getViewModelStore();
        }
        ...
    }
    

    FragmentActivity.HostCallbacksgetViewModelStore()方法,直接调用了FragmentActivitygetViewModelStore()方法,即调用了其父类ComponentActivitygetViewModelStore()方法。

    所以FragmentManager.attachController()方法内,通过host也能获取到ComponentActivityViewModelStore

    接下来,我们再来看一下FragmentManagerViewModelgetInstance()方法。

    FragmentManagerViewModel --> getInstance方法

    final class FragmentManagerViewModel extends ViewModel {
        private static final String TAG = FragmentManager.TAG;
    
        private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() {
            @NonNull
            @Override
            @SuppressWarnings("unchecked")
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                FragmentManagerViewModel viewModel = new FragmentManagerViewModel(true);
                return (T) viewModel;
            }
        };
    
        @NonNull
        static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
            ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore,
                    FACTORY);
            return viewModelProvider.get(FragmentManagerViewModel.class);
        }
       
    }
    

    FragmentManagerViewModel是一个ViewModelgetInstance(ViewModelStore)方法会先从传入的ViewModelStore(即ComponentActivityViewModelStore)中获取,如果没有则使用FACTORY进行创建FragmentManagerViewModel

    说明:

    1. 传入的ViewModelStoreComponentActivityViewModelStore,一开始ViewModelStore内是没有FragmentManagerViewModel的,所以创建FragmentManagerViewModel并存入其ComponentActivityViewModelStore中。
    2. 由于ComponentActivityViewModelStore配置变更后实例不变,所以FragmentManagerViewModel.getInstance()方法也能从ComponentActivityViewModelStore中获取到配置变更前存入的FragmentManagerViewModel实例

    说完了FragmentManagerViewModel的创建,我们再来看一下其getViewModelStore()方法。

    FragmentManagerViewModel --> getViewModelStore方法

    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
        ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
        if (viewModelStore == null) {
            viewModelStore = new ViewModelStore();
            mViewModelStores.put(f.mWho, viewModelStore);
        }
        return viewModelStore;
    }
    

    getViewModelStore(Fragment)方法,获取到指定FragmentViewModelStore,如果没有则进行创建保存mViewModelStores中,mViewModelStoresViewModelStoreMap集合。

    说明:

    1. 为什么FragmentManagerViewModel.getViewModelStore(Fragment)方法,要传入Fragment才能获取到ViewModelStore
    • 因为FragmentManagerViewModel,保存到了ComponentActivityViewModelStore中,所以每个Fragment获取到的FragmentManagerViewModel实例相同,所以需要传入Fragment实例区分是获取ViewModelStore集合的哪个。
    1. 为什么Fragment配置变更前后获取到的ViewModelStoreViewModel实例不变
    • 因为ComponentActivity配置变更前后获取到的ViewModelStoreViewModel实例不变,所以存在ComponentActivityViewModelStore中的FragmentManagerViewModel实例不变,所以存在mViewModelStores的各个FragmentViewModelStore实例不变,所以ViewModel实例不变

    代码流程:

    1. Fragmentattach的时候,获取到了ComponentActivityViewModelStore,创建FragmentManagerViewModel并存入到ComponentActivityViewModelStore中。
    2. FragmentManagerViewModel.getViewModelStore(Fragment)方法,通过FragmentmViewModelStores中获取到对应的ViewModelStore,如果没有则进行创建后保存到mViewModelStores中。

    ViewModel是如何被清除的?

    要想分析ViewModel是如何被清除的,则需要分析ViewModelStore是如何被清除的。

    Activity

    通过引用查找,我们发现在ComponentActivity的构造方法里面调用了ViewModelStore的清除操作。

    ComponentActivity类

    public ComponentActivity() {
        Lifecycle lifecycle = getLifecycle();
        //noinspection ConstantConditions
        if (lifecycle == null) {
            throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
                    + "constructor. Please make sure you are lazily constructing your Lifecycle "
                    + "in the first call to getLifecycle() rather than relying on field "
                    + "initialization.");
        }
        ...
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    // Clear out the available context
                    mContextAwareHelper.clearAvailableContext();
                    // And clear the ViewModelStore
                    if (!isChangingConfigurations()) {
                        // 不是配置变更,清除全部ViewModel。
                        getViewModelStore().clear();
                    }
                }
            }
        });
        ...
    }
    

    使用Lifecycle观察当前生命周期的状态,如果事件处于ON_DESTROY并且不是配置变更,则清空全部ViewModel

    说明:

    1. ActivityViewModel是如何被清除的?
    • 使用Lifecycle观察当前生命周期的状态,如果事件处于ON_DESTROY并且不是配置变更,则清空全部ViewModel

    Fragment

    通过引用查找,我们发现在FragmentManagerViewModelclearNonConfigStateInternal方法里面调用了ViewModelStore的清除操作。

    FragmentManagerViewModel --> clearNonConfigStateInternal方法

    void clearNonConfigState(@NonNull Fragment f) {
        if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
            Log.d(TAG, "Clearing non-config state for " + f);
        }
        clearNonConfigStateInternal(f.mWho);
    }
    
    void clearNonConfigState(@NonNull String who) {
        if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
            Log.d(TAG, "Clearing non-config state for saved state of Fragment " + who);
        }
        clearNonConfigStateInternal(who);
    }
    
    private void clearNonConfigStateInternal(@NonNull String who) {
        // Clear and remove the Fragment's child non config state
        FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(who);
        if (childNonConfig != null) {
            childNonConfig.onCleared();
            mChildNonConfigs.remove(who);
        }
        // Clear and remove the Fragment's ViewModelStore
        // 获取到对应Fragment的ViewModelStore
        ViewModelStore viewModelStore = mViewModelStores.get(who);
        if (viewModelStore != null) {
        // 清除全部ViewModel。
            viewModelStore.clear();
            mViewModelStores.remove(who);
        }
    }
    

    clearNonConfigStateInternal(String)方法,会获取到对应FragmentViewModelStore,然后调用其clear()方法清除全部ViewModel

    通过引用查找,我们发现在clearNonConfigStateInternal(String)方法被clearNonConfigState(Fragment)clearNonConfigState(String)方法调用,然后它两又被几处调用,最后通过Debug发现FragmentStateManager.destroy()方法,执行了clearNonConfigState(Fragment)方法。

    FragmentStateManager --> destroy方法

    void destroy() {
        ...
        if (shouldDestroy) {
            FragmentHostCallback<?> host = mFragment.mHost;
            boolean shouldClear;
            if (host instanceof ViewModelStoreOwner) {
                shouldClear = mFragmentStore.getNonConfig().isCleared();
            } else if (host.getContext() instanceof Activity) {
                Activity activity = (Activity) host.getContext();
                shouldClear = !activity.isChangingConfigurations();
            } else {
                shouldClear = true;
            }
            if ((beingRemoved && !mFragment.mBeingSaved) || shouldClear) {
            // 执行FragmentManagerViewModel的clearNonConfigState(Fragment),清除不会因配置变更而改变的状态。
                mFragmentStore.getNonConfig().clearNonConfigState(mFragment);
            }
            ...
        }
        ...
    }
    

    hostFragmentActivity.HostCallbacks,它实现了ViewModelStoreOwner接口,所以会走第一个if。只要shouldCleartrue的时候,就会执行到FragmentManagerViewModelclearNonConfigState(Fragment)方法,我们来看一下FragmentManagerViewModelisCleared()方法的返回值是什么?

    FragmentManagerViewModel --> isCleared方法

    final class FragmentManagerViewModel extends ViewModel {
    
        @Override
        protected void onCleared() {
            if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                Log.d(TAG, "onCleared called for " + this);
            }
            // 标记已经被清理
            mHasBeenCleared = true;
        }
    
        boolean isCleared() {
            return mHasBeenCleared;
        }
    }
    

    FragmentManagerViewModel是一个ViewModel,被添加到了ComponentActivityViewModelStore中,当ComponentActivityViewModelStore被清除的时候(事件为ON_DESTROY并且不是配置变更),会调用ViewModelonCleared()方法,则mHasBeenClearedtrue,即isCleared()方法返回为true

    因为isCleared()方法返回为true,所以FragmentStateManager.destroy()方法内会执行到FragmentManagerViewModelclearNonConfigState(Fragment)方法,会获取到对应FragmentViewModelStore,然后调用其clear()方法清除全部ViewModel

    说明:

    1. FragmentViewModel是如何被清除的?
    • FragmentManagerViewModel是一个ViewModel,被添加到了ComponentActivityViewModelStore中,当ComponentActivityViewModelStore被清除的时候(事件为ON_DESTROY并且不是配置变更),会调用ViewModelonCleared()方法,则mHasBeenClearedtrue,即isCleared()方法返回为true,所以FragmentStateManager.destroy()方法内会执行到FragmentManagerViewModelclearNonConfigState(Fragment)方法,会获取到对应FragmentViewModelStore,然后调用其clear()方法清除全部ViewModel

    总结

    以上就是全面的Jetpack-ViewModel源码了!之后会出Jetpack其它源码系列,请及时关注。如果你有什么问题,大家评论区见!

    最后推荐一下我的网站,开发者的技术博客: devbolg.cn ,目前包含android相关的技术,之后会面向全部开发者,欢迎大家来体验!

    相关文章

      网友评论

          本文标题:Jetpack-ViewModel源码解析

          本文链接:https://www.haomeiwen.com/subject/usliqrtx.html