ViewModel

    首要看下ViewModel的结构。

ViewModel源码解析

    ViewModel类结构简单,是一个抽象类,我们运用时分,需求继承该类,来定义我们自己的ViewModel。内部定义的onCleared方法会在clear方法中被调用。

ViewModel源码解析

    clear方法可以被外部调用,当被调用时分,可以触发onCleared方法。

    我们暂时可以只关注这么多,继续向后分析。

AndroidViewModel

    AndroidViewModel继承自ViewModel,内部只是包含了一个变量application可供我们运用。

ViewModel源码解析

生成ViewModel实例

    实际运用ViewModel过程中,我们需求拿到viewModel方针进行操作。拿取viewModel方针实例分几种方法,我们依次分析下。

方法1:NewInstanceFactory

    运用方法:

ViewModelProvider.NewInstanceFactory.instance.create(CustomViewModel::class.java)

    从运用方法可以看到,直接运用的是NewInstanceFactory中的instance方针的方法create来创建viewModel。我们看下这个instance和create方法。

ViewModel源码解析

    根据源码红框逻辑可以知道,instance在当时进程中存在唯一性,是个单例方针。

ViewModel源码解析

    它的create方法也很简单,通过反射new一个实例出来,所以该方法每次调用都会生成一个新的viewModel方针出来。

方法1 特征总结
  1. 每次生成的viewModel都是一个单独的新方针
  2. 该方法生成的viewModel不会和任何view或activity或fragment的生命周期有相关。效果域没了后,方针会被回收。
  3. onCleared方法永久不会被触发,因为没有当地会调用其clear方法
方法2:AndroidViewModelFactory

    怎样运用

ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(CustomViewModel::class.java)

    AndroidViewModelFactory继承自NewInstanceFactory,AndroidViewModelFactory要求有必要传入一个Applciation。

    getInstance(application)也是一个单例方针,APP进程内存活。

    create方法对外暴露了两种入参方法:

ViewModel源码解析

    其间第一种方法,答应传入外部我们自定义的一个CreationExtra方针,这个CreationExtra其实本意是为了封装一些我们实例化时分需求传给ViewModelde 入参。这儿是将application传入了进来。

    关于第二种方法和NewInstanceFactory相同,直接生成一个viewModel方针实例回来。

方法2 特征总结
  1. 每次生成的viewModel都是一个单独的新方针
  2. 该方法生成的viewModel不会和任何view或activity或fragment的生命周期有相关。效果域没了后,方针会被回收。
  3. onCleared方法永久不会被触发,因为没有当地会调用其clear方法
  4. 答应我们传入自定义的CreateExtra方针,但是没啥用
  5. 内部会维护一个application方针

方法3:ViewModelProvider

    怎样运用

ViewModelProvider(activity)[ActivityMainViewModel::class.java]
ViewModelProvider(fragment)[ActivityMainViewModel::class.java]

    ViewModelProvider也具有三个结构函数,答应我们传入一个ViewModelStoreOwner方针。AndroidX的activity和fragment都有完结这个接口,所以这儿我们可以直接传入activity或许fragment方针。

ViewModel源码解析

    activity和fragment都会创建自己的CreationExtra方针用于存储生成的viewModel方针。所以我们通过该方法获取到的viewModel是同一个方针。

ViewModel源码解析

ViewModelStoreOwner

    ViewModelStoreOwner 接口需求完结者回来一个ViewModelStore方针。看下ViewModelStore方针结构:

ViewModel源码解析

    该方针中会维护一个Map,map保存的是key和viewModel的映射联络。所以关于activity和fragment完结了该接口,他们会创建自己的ViewModelStore方针,用于保存创建好的viewModel方针到map中。然后完结了每次通过同一个activity方针实例获取到的viewModel都是同一个。

ViewModel源码解析

ViewModel源码解析

    这个是activity完结了接口ViewModelStore的源码,可以看到回来了一个ViewModelStore方针实例并保存到了当时方针中。然后证实了我们上述理念。

我们理清了内部大致架构原理,我们接下来从get方法下手,详细看下集结流程:

  1. 实例化ViewModelProvider时分,传入一个activity
  2. 调用ViewModelProvider的get方法获取viewModel
  3. 从ViewModelStore中的map中查找对应的viewmodel,找到则回来
  4. 找不到则新建
  5. 同时从CreationExtra中读取参数调用factory的create方法创建viewModel
clear方法

从源码中可以直接看到,当activity的onDestory被调用后,会调用ViewModelStore的clear方法,清空当时map集结中保存的全部viewModel。

ViewModel源码解析

  • 关于ViewModelProvider的几个入参
  1. ViewModelProvider中的factory用于定义创建ViewModel的方法方法,比如是否传入参application等等。
  2. ViewModelStoreOwn用于保存viewModel和其映射。
  3. CreationExtra传递入参,用于创建viewModel时分factory运用
  • 架构

ViewModel源码解析

  • 关于传递context引起的内存泄露
  1. 我们假设直接通过上述方法1和方法2来创建viewModel,那么这个viewModel其实就是一个单例方针,可以在APP生命周期内任何当地运用,假设我们传入context,那么context便存在无法被正常开释的状况。
  2. 通过方法3生成的viewModel,虽然存储于activity中,但是当activity销毁时分,只是将activity中保存的map进行了清空,而viewModel方针实例依然可能在工作中,此时假设持有context,依然会形成泄露。