美文网首页
Viewmodel的原理

Viewmodel的原理

作者: 烧伤的火柴 | 来源:发表于2020-05-07 11:16 被阅读0次

    介绍

    google的Jetpack推出的Viewmodel会绑定组件的生命周期,当Activity finish的时候,Viewmodel会执行onCleared()方法释放资源,避免内存泄漏。

    使用

    1.定义Viewmodel

    class ShareViewModel: ViewModel() {
        val mutableLiveData:MutableLiveData<String> = MutableLiveData()
    }
    

    2.使用

    val viewModel = ViewModelProvider(activity as ViewModelStoreOwner)[ShareViewModel::class.java]
    
            viewModel.mutableLiveData.observe(activity as LifecycleOwner, Observer {
                textView.text = it
            })
    

    源码分析

    ViewModelProvider构造

      public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
            this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                    ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                    : NewInstanceFactory.getInstance());
        }
    
     public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
            mFactory = factory;
            mViewModelStore = store;
        }
    

    andoidx.activity:activity:1.0.0@aar中的ComponentActivity实现了ViewModelStoreOwner接口
    andoidx.activity:activity:1.1.0@aar中的ComponentActivity实现了ViewModelStoreOwner接口和HasDefaultViewModelProviderFactory接口
    我们分析一个1.0.0的ComponentActivity,那么mFactory 就是NewInstanceFactory实例
    我们看一下ComponentActivity的getViewModelStore

       public ViewModelStore getViewModelStore() {
         ...
                if (mViewModelStore == null) {
                    mViewModelStore = new ViewModelStore();
                }
            }
            return mViewModelStore;
        }
    

    所以ComponentActivity的mViewModelStore 是ViewModelStore的实例

    get方法得到Viewmodel

      public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
            String canonicalName = modelClass.getCanonicalName();
            if (canonicalName == null) {
                throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
            }
            return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
        }
    
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
            ViewModel viewModel = mViewModelStore.get(key);
    
            if (modelClass.isInstance(viewModel)) {
                if (mFactory instanceof OnRequeryFactory) {
                    ((OnRequeryFactory) mFactory).onRequery(viewModel);
                }
                return (T) viewModel;
            } else {
                //noinspection StatementWithEmptyBody
                if (viewModel != null) {
                    // TODO: log a warning.
                }
            }
            if (mFactory instanceof KeyedFactory) {
                viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
            } else {
                viewModel = (mFactory).create(modelClass);
            }
            mViewModelStore.put(key, viewModel);
            return (T) viewModel;
        }
    

    第一步是从mViewModelStore的缓存中根据key查询ViewModel,如果缓存中存在 就直接返回,否则就根据mFactory create一个ViewModel然后存储到mViewModelStore中。
    根据前边的分析mFactory 是NewInstanceFactory。

    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                //noinspection TryWithIdenticalCatches
                try {
                    return modelClass.newInstance();
                } catch (InstantiationException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                }
            }
    

    这里我们发现Viewmodel是根据Class 反射创建出来的实例。

    我们有时候看到一个Activity中多个Fragment使用Viewmodel共享数据,他们都是通过使用的用一个activity创建的ViewModelProvider,那么ViewModelProvider中的mViewModelStore是同一个,即共用一个缓存。

    相关文章

      网友评论

          本文标题:Viewmodel的原理

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