ViewModel 源码分析
2021/4/26 1:26:30
本文主要是介绍ViewModel 源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
预备知识
在Android
中我知道Activity
有一个onSaveInstanceState
函数,用于在Activity
在不幸被回收或者配置改变时存储序列化对象,在下次重建时onRestoreInstanceState
取出序列化数据.
要是我们有非序列数据呢?
public Object onRetainNonConfigurationInstance
和public Object getLastNonConfigurationInstance()
可以帮助我存储任意非序列化数据,用于下次重建复用对象
onRetainNonConfigurationInstance
class Activity public Object onRetainNonConfigurationInstance() { return null; } }
该函数在onStop
和onDestry
之间回调,你可以返回任意对象,该对象会在下次重建Activity调用getLastNonConfigurationInstance
获得.
我们看下一个demo:
class Person { } class MainActivity : Activity() { var myString: Person? = null private val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val lastNonConfigurationInstance = lastNonConfigurationInstance if (lastNonConfigurationInstance != null) { Log.e(TAG, "onCreate: lastNonConfigurationInstance hash:" + lastNonConfigurationInstance + "") myString = lastNonConfigurationInstance as Person } if (myString == null) { myString = Person() } Log.e(TAG, "onCreate: myString hash:" + myString + "") } override fun onRetainNonConfigurationInstance(): Person? { return myString } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) } }
输出
onCreate: myString hash:com.example.leakstudy.Person@2b4aece1
进行旋转屏幕(Activity会重建)
//重建前 onCreate: myString hash:com.example.leakstudy.Person@2b4aece1 //重建后 onCreate: lastNonConfigurationInstance hash:com.example.leakstudy.Person@2b4aece1 onCreate: myString hash:com.example.leakstudy.Person@2b4aece1
而我们的viewmodel便是利用这一特性完成存储.
ViewModelStore的存储
ViewModelStoreOwner
是一个重要的接口,且声明如下:
public interface ViewModelStoreOwner { @NonNull ViewModelStore getViewModelStore(); }
实现ViewModelStoreOwner
接口的对象必须在configration
改变时存储好自己ViewModelStore
对象,并且在这个对象被回收时候调用ViewModelStore
的onClear
函数,而ComponentActivity
对象便实现了这个接口.
public class ComponentActivity extends androidx.core.app.ComponentActivity implements ViewModelStoreOwner,
我们在看一下ViewModelStore
public class ViewModelStore { //存储所有的viewModel,键为ViewModel的全类名. private final HashMap<String, ViewModel> mMap = new HashMap<>(); //放一个新的viewmodel final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); //如果存在旧元素那么调用oncreard if (oldViewModel != null) { oldViewModel.onCleared(); } } final ViewModel get(String key) { return mMap.get(key); } Set<String> keys() { return new HashSet<>(mMap.keySet()); } /** * 调用所有的viewmodel 的clear函数 */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.clear(); } mMap.clear(); } }
我们继续研究ComponentActivity
的实现
//ComponentActivity.java public class ComponentActivity extends androidx.core.app.ComponentActivity implements ViewModelStoreOwner{ static final class NonConfigurationInstances { Object custom; ViewModelStore viewModelStore; } private ViewModelStore mViewModelStore; NonConfigurationInstances mLastNonConfigurationInstances; //activity在回收或者改变时configration存储数据 public final Object onRetainNonConfigurationInstance() { Object custom = onRetainCustomNonConfigurationInstance(); //将viewmodel存储到NonConfigurationInstances对象中 ViewModelStore viewModelStore = mViewModelStore; if (viewModelStore == null) { 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; } //我们看下如何返回viewmodel @Override public ViewModelStore getViewModelStore() { if (mViewModelStore == null) { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { // Restore the ViewModelStore from NonConfigurationInstances mViewModelStore = nc.viewModelStore; } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } } return mViewModelStore; } }
我们知道viewmodel
会在activity
被意外非回收销毁时会调用Viewmodel.onCleared
函数,而Viewmodel.onCleared
是被mViewModelStore.clear
回调的.但是我们需要区分调用Destroy
是否需要考虑复用的情况,也是正常销毁还是回收在售后重建.
public ComponentActivity() { Lifecycle lifecycle = getLifecycle(); getLifecycle().addObserver(new LifecycleEventObserver() { @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { //on_Destroy的根据是否是配置改变确定是否需要调用clear函数 if (event == Lifecycle.Event.ON_DESTROY) { if (!isChangingConfigurations()) { getViewModelStore().clear(); } } } }); //mChangingConfigurations会在onstop时候进行判断 public boolean isChangingConfigurations() { //mChangingConfigurations位于activity return mChangingConfigurations; } }
ViewModel的创建
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val viewModelProvider = ViewModelProvider(this, AndroidViewModelFactory(this.application)) val viewModel = viewModelProvider.get(MyViewModel::class.java) println("MainActivity.onCreate") } }
//ViewModelProvider.java public class ViewModelProvider { public interface Factory { <T extends ViewModel> T create(@NonNull Class<T> modelClass); } }
public class ViewModelProvider { private final Factory mFactory; private final ViewModelStore mViewModelStore; public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) { this(owner.getViewModelStore(), factory); } public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) { mFactory = factory; mViewModelStore = store; } //获取viewmodel实例 public <T extends ViewModel> T get(@NonNull Class<T> modelClass) { String canonicalName = modelClass.getCanonicalName(); return get(DEFAULT_KEY + ":" + canonicalName, modelClass); } //最终调用这 public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) { //如果mViewModelStore没有存储这个viewmodel,将返回null ViewModel viewModel = mViewModelStore.get(key); //model有可能是空,如果是空必然返回false if (modelClass.isInstance(viewModel)) { return (T) viewModel; } else { //预留代码 if (viewModel != null) { } } //判断传入的factory类型,我们这里直接看false即可 if (mFactory instanceof KeyedFactory) { viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass); } else { //调用factory.create完成viewmodel viewModel = (mFactory).create(modelClass); } //将创建的viewimodel放入mViewModelStore mViewModelStore.put(key, viewModel); return (T) viewModel; } }
我们最后看一个库里一个默认实现AndroidViewModelFactory
.
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory { private static AndroidViewModelFactory sInstance; @NonNull public static AndroidViewModelFactory getInstance(@NonNull Application application) { if (sInstance == null) { sInstance = new AndroidViewModelFactory(application); } return sInstance; } private Application mApplication; public AndroidViewModelFactory(@NonNull Application application) { mApplication = application; } @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { //当前modelClass类是AndroidViewModel或者父类 if (AndroidViewModel.class.isAssignableFrom(modelClass)) { try { //返回新的实例对象 return modelClass.getConstructor(Application.class).newInstance(mApplication); } catch (NoSuchMethodException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InvocationTargetException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } //super.create是利用空构造函数实现的 return super.create(modelClass); } }
viewmodel
整体比较简单.
这篇关于ViewModel 源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26手写消息中间件:从零开始的指南
- 2024-11-26Java语音识别项目资料:新手入门教程
- 2024-11-26JAVA语音识别项目资料:新手入门教程
- 2024-11-26Java语音识别项目资料:入门与实践指南
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料:新手入门教程
- 2024-11-25Java创意资料:新手入门的创意学习指南
- 2024-11-25JAVA对接阿里云智能语音服务资料详解:新手入门指南
- 2024-11-25Java对接阿里云智能语音服务资料详解