JetPack之ViewModel最新源码详细分析
本⽂会基于最新版ViewModel使⽤⽅法与源码进⾏详细分析,从注册到实现ViewModel界⾯数据如何保存与管理全部涉及。
**
简介:
**ViewModel是JetPack系列库之⼀,它⽤来对组件的界⾯数据进⾏管理,且当组件的状态发⽣改变时数据依然留存。
优点:1.当所依赖组件的状态发⽣改变时,例如屏幕旋转等,界⾯数据不会发⽣改变
2.实现MVVM架构的基础,在⽇常开发中,ViewModel就是MVVM架构的VM层,它相当于MVP架构的present,我们可以将业务逻辑以及数据交互的部分放⼊ViewModel中。
源码分析:
版本:viewmodel:1.1.1
此处使⽤的⽰例代码与livedata源码分析的相同,不影响流程分析
⾸先构造⼀个继承于ViewModel的类
接着创建⼀个factory 实例传⼊ViewModelProvider(this,factory )中去并调⽤get⽅法将我们的ViewMod
el作为参数传⼊。
此处需要注意的是在以前的版本中直接通过 ViewModelProviders.of(this).get()⽅法来完成这个操作的。在最新的版本中已经取消了of⽅法,并且构造⽅法必须要传⼊2个参数
查看ViewModelProvider的构造⽅法可看出构造ViewModelProvider时必须传⼊2个参数才⾏,其中第⼀个参数为ViewModelStore,第⼆个参数为factory,
ViewModelStore⽤来存储和管理ViewModel,factory则⽤来对ViewModel进⾏实例化。此时构建ViewModelProvider时传⼊的参数为所依赖的组件的ViewModelStore,也就是说,我们通过组件的ViewModelStore来对ViewModel进⾏存储和管理。
其中factory需要我们在构造的时候进⾏传⼊,ViewModelProvider给我们提供了3种实例化的⽅法,分别是简单⼯⼚模式构造,通过反射构造实例,以及我们⾃⼰实现factory构造实例。
当我们使⽤ViewModelProvider.NewInstanceFactory()构造实例时,查看源码可看出,它实现了Factory 接⼝,并且在其内部的create⽅法中会调⽤我们在之前get⽅法中传⼊的viewmodel的newInstance⽅法。这个⽅法需我们⾃⼰在viewmodel中去实现,⽤来返回viewmodel实例,如果实例化出错则会抛出异常
public static class NewInstanceFactory implements Factory {
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
//返回modelClass实例对象
wInstance();
} 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);
}
}
}
使⽤AndroidViewModelFactory ⽅式反射⽣成ViewModel,该Factory使⽤单例模式进⾏构建 ,所以它的⽣命周期等同于应⽤程序的⽣命周期,且只有⼀个实例,推荐使⽤此模式来获取factory,当它的create⽅法被调⽤时,会通过application利⽤反射创建⼀个ViewModel实例并返回。
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) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
//通过反射创建viewmodel
Constructor(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);
}
}
ate(modelClass);
}
}
第三种⽅式就是直接实现Factory接⼝,并⾃⼰实现create⽅法,我们需要在该create⽅法内,返回viewmodel的实例
/**
* Implementations of {@code Factory} interface are responsible to instantiate ViewModels.
*/
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
* <p>
*
* @param modelClass a {@code Class} whose instance is requested
* @param <T> The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
当我们在构造ViewModelProvider时,会将我们传⼊的这2个参数进⾏保存,
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
当我们调⽤get⽅法时
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
//获取到ViewModel的类名
String canonicalName = CanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
//再次进⾏回调
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
在该⽅法内⾸先会从ViewModelStore中通过key去获取ViewModel ,这个key就是上⾯的DEFAULT_KEY +类名。如果到则直接返回,否则调⽤factory的create⽅法创建ViewModel实例放⼊ViewModelStore进⾏管理和保存并返回该实例
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//从ViewModelStore中获取viewModel
ViewModel viewModel = (key);
//如果到则直接返回
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
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);
//noinspection unchecked
return (T) viewModel;
}
ViewModelStore 内部通过hashmap来对viewmodel进⾏管理,
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) {
}
}
final ViewModel get(String key) {
(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
到此处为⽌源码部分分析完毕,如何触发viewmodel对组件界⾯的状态保存继续分析
上⾯说过在构建ViewModelProvider时传⼊的ViewModelStore来⾃于构建它所传⼊的this,也就是当前组件,我们知道ViewModelStore起到了对viewmodel的管理作⽤,viewmodel的获取和存储都是通过它来完成。
public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
在这⾥调⽤了组件的ViewModelStore()⽅法
ViewModelStore(), factory);
}
追踪getViewModelStore⽅法,发现它是⼀个ViewModelStoreOwner 接⼝中的⼀个⽅法
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
android最新版* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论