内容简介:从图可以看出来,ViewModel 与 LiveData 和 Paging 是谷歌新组件,同时它是 android.arch.lifecycle 包里面的类,可以支持 activity 和 fragment 共享数据(比如在 fragment 获取 activity 搜索框的内容)当然 activity 销毁了数据就不存在了;又或者是 fragment 与子 fragment 共享数据(比如 fragment 里面嵌套了 viewpager , viewpager 里又有 fragemnt)。创建一个类传
从图可以看出来,ViewModel 与 LiveData 和 Paging 是谷歌新组件,同时它是 android.arch.lifecycle 包里面的类,可以支持 activity 和 fragment 共享数据(比如在 fragment 获取 activity 搜索框的内容)当然 activity 销毁了数据就不存在了;又或者是 fragment 与子 fragment 共享数据(比如 fragment 里面嵌套了 viewpager , viewpager 里又有 fragemnt)。
使用方法
//build.gralde implementation 'android.arch.lifecycle:extensions:1.1.1' //包括了 viewmodel 和 livedata implementation 'android.arch.lifecycle:compiler:1.1.1' implementation 'android.arch.lifecycle:common-java8:1.1.1' 复制代码
创建一个类传字符串,然后在 activity 实例化并且赋值。
//KeywordModel.kt class KeywordModel : ViewModel() { var keyword: MutableLiveData<String>? = MutableLiveData() fun getKeyWord(): LiveData<String> { return keyword!! } fun setKeyWord(key: String) { keyword?.value = key } } //MainActivity.kt val keywordModel=ViewModelProviders.of(this).get(KeywordModel::class.java) //在activity实例化 keywordModel.setKeyWord("siri") //赋值 复制代码
在fragment 获取值
//ExampleFragment.kt val keywordModel = ViewModelProviders.of(activity as MainActivity).get(KeywordModel::class.java) keywordModel.getKeyWord().observe(this, Observer<String> { mPresenter.requestArticleList(requireNotNull(it), true) }) 复制代码
以上就完成了 ViewModel 的基本使用了。
源码分析
在分析源码之前,应该思考一下,如果这个功能由你来写,你会是怎么实现,用什么数据结构去存数据,然后根据这个功能,可以拓展出什么其他用途。
首先看创建方法。ViewModelProviders 的 of 方法可以传入 fragment 或者是 activity,就是说你可以在fragment 或者 activity 创建 viewmodel,而这个 viewmodel 只会依赖你的创建的 activity 或者是 fragment(都是同一个viewmodel)。我们先来分析 传入参数是 activity 的这种情况。
//ViewModelProviders.java public static ViewModelProvider of(@NonNull FragmentActivity activity) { return of(activity, null); } 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(ViewModelStores.of(activity), factory); } 复制代码
调用了两个参数的 of 方法,在 of 方法里面,通过 activity 来获取 applicaiton 从而来创建默认的 AndroidViewModelFactory 工厂。 这个工厂是 ViewModelProvider 的静态内部类。主作用是同是通过反射来获取 viewmodel
//AndroidViewModelFactory.java public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { if (AndroidViewModel.class.isAssignableFrom(modelClass)) { try { return modelClass.getConstructor(Application.class).newInstance(mApplication); } catch (Exception e) { throw new RuntimeException("", e); } } return super.create(modelClass); } 复制代码
还有另外一个参数 ViewModelStores.of(activity),判断了当前activity有没有实现 ViewModelStoreOwner 接口,而我们没实现,就下一步吧。调用了 HolderFragment 的 holderFragmentFor 来创建一个 holderFragment, 添加到 activity 上(当然这个fragment 没界面),而这个 fragment 上有 mViewModelStore 的实例。
//ViewModelStores.java public static ViewModelStore of(@NonNull FragmentActivity activity) { if (activity instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) activity).getViewModelStore(); } return holderFragmentFor(activity).getViewModelStore(); } 复制代码
而在 ViewModelStore 里面有 hashmap ,通过 key 获取存储 viewmodel 。所以 viewmodel 使用了hashmap来存储 viewmodel 啦。
//ViewModelStore.java 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); } public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } } 复制代码
而看回 ViewModelProvider 这个类,通过get方法来获取viewmodel,从下面的的 get 方法可以看到 hashmap 的 key 是由DEFAULT_KEY 前缀和的 viewmodel 的 canonicalName 来组成。并且get的时候 会先从hashmah 中获取viewmodel ,不存在这个viewmodel,再从 mFactory 里面创建 viewmodel ,并存进 hashmap。
//ViewModelProvider.java 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)) { //noinspection unchecked return (T) viewModel; } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } viewModel = mFactory.create(modelClass); mViewModelStore.put(key, viewModel); //noinspection unchecked return (T) viewModel; } 复制代码
同理
当viewmodelproviders.of 传入fragment时,也会走上面的流程,只不过生成holderfragment的时候用getChildFragmentManager()
//HolderFragment.java HolderFragment holderFragmentFor(Fragment parentFragment) { FragmentManager fm = parentFragment.getChildFragmentManager(); HolderFragment holder = findHolderFragment(fm); if (holder != null) { return holder; } holder = mNotCommittedFragmentHolders.get(parentFragment); if (holder != null) { return holder; } parentFragment.getFragmentManager() .registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false); holder = createHolderFragment(fm); mNotCommittedFragmentHolders.put(parentFragment, holder); return holder; } 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Software Paradigms
Stephen H. Kaisler / Wiley-Interscience / 2005-03-17 / USD 93.95
Software Paradigms provides the first complete compilation of software paradigms commonly used to develop large software applications, with coverage ranging from discrete problems to full-scale applic......一起来看看 《Software Paradigms》 这本书的介绍吧!