Architecture Components ViewModel的控制。
前言
作为MVVM 系列的第二篇,我们来看一下之前提出的第二个问题,就是ViewModel是如果控制生命周期的,并且保证在一定范围内的唯一性。
ViewModel的生命周期
先上一张官方的生命周期的图:
可以看到ViewModel只有一个生命周期函数,那就是onCleared(),会在Activity的onDestroy之后执行, 那么相对应Fragment的生命周期是再哪个函数之后执行?这里先剧透一下,也是在onDestroy之后执行。
在看官方的实现之前,我们先简单的想一下怎么才能实现Activity/Fragment生命周期函数的监听?思考三秒钟,联想到上一篇中的做法,可以想到利用Fragment和Activity中添加的Fragment来感知宿主的生命周期。并且这里我们只需要监听销毁时候的函数就行。下面进行具体的分析。
ViewModel的实现过程
给出一个最简单的创建的示例:
MainActivityViewModel viewModel=ViewModelProviders.of(this).get(MainActivityViewModel.class);
代码很好理解,获取当前类的ViewModel提供者,之后在传入需要获得的ViewModel的类型。先看一下ViewModelProviders都做了什么?
如果传入的this是Fragment就先判断下是否已经关联到Activity上,没有就抛异常。之后就初始化一个sDefaultFactory,用于创建ViewModelProvider。在ViewModelProvider的构造函数中还需要一个ViewModelStores。
两个工厂方法用于创建ViewModelStore。接下来就是本文的重点了。还是以Activity为例,Fragment的大同小异。
简单说一下这个方法都做什么了。先获取FragmentManager,查找当前的Activity有没有已经添加过HoldFragment,没有的话则去还没有添加到Activity/Fragment的HoldFragment列表中去查询,看看有没有已经创建的HoldFragment,只不过还没有添加上去。如果还没有的话那就创建一个新的HoldFragment,同时给Application注册一个Activity的生命周期监听,再把创建的HoldFragment添加到缓存列表中。现在来看看这个HoldFragment。
拥有两个属性sHoldFragmentManager和mViewStore。在onCreate方法中执行一个函数,将在未添加到Activity/Fragment的HoldeFragment列表中删除当前的Activity/Fragment。然后在onDestory方法中调用mViewStore的clear方法,这里就会间接的调用到ViewModel的onCleared()方法。更多的细节可以去看源码,这里简单的总结一下都做了什么。
- 查找当前的Activity/Fragment中是否有已经添加的HoldFragment,有则返回。
- 查找当前的Activity/Fragment是否有已经创建但是并未添加的HoldFragment,有则返回。
- 注册Activity/Fragment的生命周期监听。
- 创建新的HoldeFragment,并添加的缓存列表。
- HoldFragment在关联到Activity/Fragment之后会在缓存中去掉当前的Activity/Fragment对应的HoldFragment
- HoldFragment在onDestory的时候会调用其成员变量mViewStore的clear方法。
回到之前创建ViewModelProvider的地方。
简单看一下,代码不难理解,先赋值成员变量,之后是查看ViewModelStore中是否有传入类型的ViewModel,没有的话就通过传入的工厂类创建一个新的ViewModel 添加到ViewModelStore中。
这样ViewModel的实现过程就差不多结束了,还是利用Fragment的方式去获取生命周期,然后再利用工厂类来创建ViewModel。
关于在一定范围内的唯一性,因为ViewModelStore是HoldFragment的成员变量,HoldFragment是通过FragmentManager添加到指定的Activity/Fragment,那么对于当前的宿主,只有一个HoldFragment,也就只有一个ViewModelStore,同时也就只有一个ViewModel。
总结
同样使用的给宿主添加Fragment的方式来获取宿主的生命周期,只不过现在只获取销毁的函数就可以。然后在HoldFragment中持有一个集合用于保存当前宿主的ViewModel,在onDestory函数中调用集合的clear方法,间接调用到ViewModel的onCleared方法,实现生命周期的控制。同时使用TAG的方式添加Fragment 使得ViewModel相对宿主是唯一的。
- 对php多态的理解
- JavaScript值延迟脚本和异步脚本
- JavaScript之arguments.callee
- JavaScript之面向对象学九(原型式继承和寄生式继承)
- ExtJs学习笔记(18)_ExtJs嵌入FCK示例
- Html与CSS快速入门01-基础概念
- 利用Fck的javascript-API创建fck编辑器
- ASPNET_WEBAPI快速学习02
- ExtJs学习笔记(17)_table布局
- Markdown快速入门
- JavaScript之apply()和call()的区别
- JavaScript之面向对象学习八(继承)
- JQuery快速入门
- JavaScript之面向对象学习七(动态原型模式、寄生构造函数模式、稳妥构造函数模式创建自定义类型)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- VUE 过滤输入框中的特殊字符 只保存中文、英文及数字
- Java 判断一个字符串是不是由数字组成
- 解决ES搜索过程中使用高亮插件导致结果不完整的问题
- Java selenuim用执行js模拟鼠标滚动的方式
- 使用puppeteer 进行批量网页截图
- dubbo 配置优先级 集群模式 负载均衡策略
- 【STM32F407开发板用户手册】第33章 STM32F407的SPI总线应用之驱动DAC8563
- Salesforce LWC学习(二十) CLI篇:新版本不支持Audience解决方案
- 【STM32F429开发板用户手册】第33章 STM32F429的SPI总线应用之驱动DAC8563
- ELK学习笔记之filbeat pod无法将容器日志发送
- 小学生看了都会的Apache配置虚拟主机教程
- 【STM32F407开发板用户手册】第34章 STM32F407的SPI总线应用之驱动DAC8501
- 学长冷月带你怒刷LeetCode之反转链表
- php面试笔记-php基础知识-变量和引用变量
- 【STM32F429开发板用户手册】第34章 STM32F429的SPI总线应用之驱动DAC8501