概览 ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。 ViewModel 对象存在的时间范围是获取 ViewModel 时传递给 ViewModelProvider 的 Lifecycle。ViewModel 将一直留在内存中,直到限定其存在时间范围的 Lifecycle 永久消失:对于 activity,是在 activity 完成时;而对于 fragment,是在 fragment 分离时。
如下图生命周期: 在系统首次调用 Activity 对象的 onCreate() 方法时请求 ViewModel。系统可能会在 activity 的整个生命周期内多次调用 onCreate(),如在旋转设备屏幕时。ViewModel 存在的时间范围是从您首次请求 ViewModel 直到 activity 完成并销毁。
特点
1.横竖屏切换,包括Activity重建,数据可依然保存。
2.同一个Activity下,Fragment之间的数据共享。同理在不同Activity中也可以共享ViewModel数据
源码分析 我们在使用时是这样创建viewmodel的:
1 ViewModelProviders.of(this).get(MyViewModel::class.java)
从上看出,Factory不传,默认为null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(activity.getViewModelStore(), factory); } // getViewModelStore是在父类FragmentActivity中的; public ViewModelStore getViewModelStore() { if (getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } return mViewModelStore; }
但是在2.2.0 中 ViewModelProviders被弃用。需要用新的方式获取:
1 ViewModelProvider(this,ViewModelProvider.NewInstaanceFactory()).get(MyViewModel::class.java)
接着看ViewModelStoreOwner,就是this,说明它是一个接口,并且,我们的Activity一定是实现了这个接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) { this(owner.getViewModelStore(), factory); } // 就是拿到ViewModelStore,如果是高版本,这里应该还有个nc判断,android-28版本nc在onCreate里 public ViewModelStore getViewModelStore() { if (getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); } // nc保存了viewModelStore,所以横竖屏切换,数据不会丢失。 if(mViewModelStore == null){ NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { mViewModelStore = nc.viewModelStore; } } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } return mViewModelStore; } //mViewModelStore专门存储ViewModel public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) { mFactory = factory; this.mViewModelStore = store; }
看以下继承关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class FragmentActivity extends ComponentActivity implements ViewModelStoreOwner, ActivityCompat.OnRequestPermissionsResultCallback, ActivityCompat.RequestPermissionsRequestCodeValidator { } // 这个接口只有一个ViewModelStore public interface ViewModelStoreOwner { @NonNull ViewModelStore getViewModelStore(); } // ViewModelStore是啥?就是存储了一个map,map里存的是viewmodel,同时提供了一个clear方法,用于清理map缓存。 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); } /** * Clears internal storage and notifies ViewModels that they are no longer used. */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } }
接着看get方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 private static final String DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"; @MainThread public <T extends ViewModel> T get(@NonNull Class<T> modelClass) { String canonicalName = modelClass.getCanonicalName(); return get(DEFAULT_KEY + ":" + canonicalName, modelClass); } @MainThread public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) { ViewModel viewModel = mViewModelStore.get(key); if (modelClass.isInstance(viewModel)) {//缓存里是否有,有就直接返回。 //noinspection unchecked return (T) viewModel; } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } viewModel = mFactory.create(modelClass);//通过mFactory创建ViewModel mViewModelStore.put(key, viewModel);//存储到mViewModelStore //noinspection unchecked return (T) viewModel;//并返回ViewModel }
那Factory如何根据class创建ViewMoel的?通过反射,拿到我们自定义的MyViewModel
1 2 3 4 5 6 7 public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { //noinspection TryWithIdenticalCatches try { return modelClass.newInstance(); } catch (Exception e) { } }
所以,ViewModelProvider(this,ViewModelProvider.NewInstaanceFactory()).get(MyViewModel::class.java) 这段代码一执行。就会通过工厂NewInstaanceFactory,反射实例化MyViewModel存储到了ViewModelStore中。 那viewmodel是啥时候销毁的?是在onDestroy生命周期中,所以,这里不需要我们手动去做,框架帮我们做了。同理,无论activity如何操作,旋转,重建,viewmode都不会销毁,数据都会保存,只有最后销毁,才清除掉。同时跟lifecycle解绑。
1 2 3 4 5 6 7 protected void onDestroy() { super.onDestroy(); if (mViewModelStore != null && !isChangingConfigurations()) { mViewModelStore.clear(); } mFragments.dispatchDestroy(); }
参考资料 developer.android.google.cn
Ursprünglicher Link: http://nunu03.github.io/2022/06/02/ViewModel源码解析/
Copyright-Erklärung: 转载请注明出处.