本文翻译自:https://medium.com/koderlabs/viewmodel-with-viewmodelprovider-factory-the-creator-of-viewmodel-8fabfec1aa4f

朋友们好,今天我向大家介绍下 ViewModel 中如何使用 ViewModelProvider.Factory.


现在开始

所以,我们首要问题是:什么是 ViewModelProvider.Factory ?让我们在不使用 ViewModelProvider.Factory 的情况下,试着创建一个 ViewModel 看看:

在活动中实例化:

有没有人注意到:当我们使用 ViewModelProviders 在活动中实例化 MyViewModel 时,从未没用过 MyViewModel 的构造方法,而都是使用 ViewModelProviders 这个类中的方法。ViewModelProviders 在内部为我们管理并调用 ViewModel 的主构造函数,创建viewmodel的实例并将该实例并返回。

那么,现在让我们看看,如果我们直接把参数传递给 MyViewModel 类的构造方法时会发生了什么:

现在,我们在活动中创建 MyViewModel 实例:

太棒了!没有发生任何错误

但是,等等。

当你运行上面这段代码的时候,你收到了 RunTimeError。程序崩溃了!!! RuntimeException 不能创建出 MyViewModel 实例。

现在我们为什么会发生这些。ViewModelProviders 的 of() 方法,在内部创建了默认的 ViewModelProvider.Factory ,从而实现了 ViewModel 的无参创建。所以,当我们在构造方法添加参数时, ViewModelProvider.Factory 的内部无法实例化 ViewModel 对象,因为 ViewModelProvider.Factory 调用主构造方法创建 ViewModel’s 实例而失败。下图是 ViewModelFactory ViewModelFactory 的默认实现。


如果你想在构造方法中添加参数,你需要编写自己的 ViewModelProvider 来创建 ViewModel 实例。

什么是 ViewModelProvider.Factory?

ViewModelProviders.Factory 接口是负责实例化 ViewModels 对象的启动装置。这意味着你需要自己写实例化 ViewModel 对象的方法。

让我们像下面这样创建自己的 ViewModelProvider.Factory :

这里有几点需要记下:

  1. 你需要通过构造方法或者其他你喜欢的途径(比如 Singleton, FactoryPattern 等等)。这是由于你在实例化 ViewModel 对象时,不能直接在活动或者碎片中调用 ViewModel 的构造方法,而且你又想去设置 ViewModel 构造方法的参数,因此你需要将参数传入 ViewModelProvider.Factory 它将会帮你创建你的 ViewModel。
  2. ViewModelProvider.Factory 是一个包含 create 方法的接口。这个 create 方法负责创建你的 VeiwModel’s 实例。
  3. modelClass.getConstructor(Int::class.java) 方法是一个整型的能够通过调用 newInstance 方法来想构造方法传值的方法。

现在就让我们通过 ViewModelProvider.Factory 在活动中创建 ViewModel 实例。

我们将参数或者依赖关系转入我们的 ViewModelProvider.Factory 以便于它能够为我们创建 ViewModel,ViewModelProviders.of( context, instanceOfViewModelFactory) 方法获得我们 ViewModelProvider.Factory 实例,现在就像之前的例子中一样,我们已经学会了创建 ViewModel 实例的过程。

所以,为什么我们需要 ViewModelProvider.Factory ?

我们心中有这样一些疑问,我们不能直接在活动或碎片中将值传入 ViewModel 构造方法中去,我需要写法来设置我们的参数值使其正常工作,这就是为什么我们需要 ViewModelProver.Factory,在一些情况下你可以不使用,但在某些特定情形下,你需要使用 ViewModelProver.Factory。

什么时候使用 ViewModelProvider.Factory

当你的 ViewModel 有依赖项,并且你需要将这些依赖项通过构造方法传入,因此,您可以模拟该依赖项并测试 ViewModel。

什么时候不应该使用 ViewModelProvider.Factory

如果你的 ViewModel 没有依赖项,这时你就不需要去自己创建 ViewModelProvider.Factory。系统自带的方法,注意帮助你创建 ViewModel。

总结

ViewModelProvider.Factory 负责帮你创建 ViewModel 实例。当你的 ViewModel 存在依赖项,且你希望测试你的 ViewModel 时,你需要创建自己的 ViewModelProvider.Factory 来通过 ViewModel 的构造方法传递依赖项,将你的数值传入 ViewModelProvider.Factory 实例中去

你的关注是我最大的动力!

ViewModel 和 ViewModelProvider.Factory:ViewModel 的创建者的更多相关文章

  1. Android 让你的 Room 搭上 RxJava 的顺风车 从重复的代码中解脱出来

    # 什么是 Room ? 谷歌为了帮助开发者解决 Android 架构设计问题,在 Google I/O 2017 发布一套帮助开发者解决 Android 架构设计的方案:Android Archit ...

  2. 每个人都要学的图片压缩终极奥义,有效解决 Android 程序 OOM

    # 由来 在我们编写 Android 程序的时候,几乎永远逃避不了图片压缩的难题.除了应用图标之外,我们所要显示的图片基本上只有两个来源: 来自网络下载 本地相册中加载 不管是网上下载下来的也好,还是 ...

  3. Android笔记之ViewModel的使用示例

    依赖 implementation 'android.arch.lifecycle:extensions:1.1.1' implementation 'com.squareup.retrofit2:r ...

  4. Android Jetpack组件 - ViewModel,LiveData使用以及原理

    本文涉及的源码版本如下: com.android.support:appcompat-v7:27.1.1 android.arch.lifecycle:extensions:1.1.1 android ...

  5. Android架构组件——ViewModel

    概述 ViewModel,从字面上理解的话,它肯定是跟视图(View)以及数据(Model)相关的.正像它字面意思一样,它是负责准备和管理和UI组件(Fragment/Activity)相关的数据类, ...

  6. Jetpack架构组件学习(2)——ViewModel和Livedata使用

    要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...

  7. ViewModel的创建

    ViewModel的创建 ViewModel本身只是ViewModel这个类的子类: class MainViewModel: ViewModel() { } 在屏幕旋转UI重建的时候, 它是如何拥有 ...

  8. 改造 Android 官方架构组件 ViewModel

    前言 Android 官方架构组件在今年 5 月份 Google I/O 大会上被公布, 直到 11 月份一直都是测试版, 由于工作比较繁忙, 期间我只是看过类似的文章, 但没有在实际项目中使用过, ...

  9. Jetpack 架构组件 LiveData ViewModel MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. 新手学习FFmpeg - 调用API完成录屏

    调用FFMPEG Device API完成Mac录屏功能. 调用FFMPEG提供的API来完成录屏功能,大致的思路是: 打开输入设备. 打开输出设备. 从输入设备读取视频流,然后经过解码->编码 ...

  2. Codeforces 985E

    题意略. 思路: 这个题目开始想的有点暴力,后来发现有搜索的性质,因此转而用动态规划.首先,我们要把这些数排个序. 定义状态:dp[i]为排序后i~n能否成功打包,1表示可以,0表示不能打包. 状态转 ...

  3. JS高级(摘自简书)

    JS高级 1. 访问对象属性(方法也是属性)的通用方式:obj['属性名'] 1. 属性名包含特殊字符,如"-".空格,访问:obj['content-type'] 2. 属性名不 ...

  4. HTML 事件属性(摘自菜鸟教程)

    HTML 事件属性 全局事件属性 HTML 4 的新特性之一是可以使 HTML 事件触发浏览器中的行为,比方说当用户点击某个 HTML 元素时启动一段 JavaScript. 如果你想学习更多关于事件 ...

  5. MySQL如何选择合适的索引

    先来看一个栗子 EXPLAIN select * from employees where name > 'a'; 如果用name索引查找数据需要遍历name字段联合索引树,然后根据遍历出来的主 ...

  6. HDU - 2255 奔小康赚大钱 KM算法 模板题

    HDU - 2255 题意: 分配n所房子给n个家庭,不同家庭对一所房子所需缴纳的钱是不一样的,问你应当怎么分配房子,使得最后收到的钱最多. 思路: KM算法裸题.上模板 #include <i ...

  7. codeforce617E-XOR and Favorite Number莫队+异或前缀和

    传送门:http://codeforces.com/contest/617/problem/E 参考:https://blog.csdn.net/keyboarderqq/article/detail ...

  8. SpringBoot项目创建及入门基础

    一:快速构建springboot项目 进入https://start.spring.io/,选择相应的springboot版本,包名,项目名,依赖 图中选择web,利用tomcat服务器进行开发 sp ...

  9. codeforces 811 E. Vladik and Entertaining Flags(线段树+并查集)

    题目链接:http://codeforces.com/contest/811/problem/E 题意:给定一个行数为10 列数10w的矩阵,每个方块是一个整数, 给定l和r 求范围内的联通块数量 所 ...

  10. 10 UA池和代理池

    在Scrapy中,引擎和下载器之间有一个组件,叫下载中间件(Downloader Middlewares).因它是介于Scrapy的request/response处理的钩子,所以有2方面作用: (1 ...