【背上Jetpack之LiveData】ViewModel 的左膀右臂 数据驱动真的香

系列文章

【背上Jetpack】Jetpack 主要组件的依赖及传递关系

【背上Jetpack】AdroidX下使用Activity和Fragment的变化

【背上Jetpack之Fragment】你真的会用Fragment吗?Fragment常见问题以及androidx下Fragment的使用新姿势

【背上Jetpack之Fragment】从源码角度看 Fragment 生命周期 AndroidX Fragment1.2.2源码分析

【背上Jetpack之OnBackPressedDispatcher】Fragment 返回栈预备篇

【背上Jetpack之Fragment】从源码的角度看Fragment 返回栈 附多返回栈demo

【背上Jetpack】绝不丢失的状态 androidx SaveState ViewModel-SaveState 分析

【背上Jetpack之ViewModel】即使您不使用MVVM也要了解ViewModel ——ViewModel 的职能边界

【背上Jetpack之Lifecycle】万物基于Lifecycle 默默无闻大用处

目录

前言

之前我们讨论过 ViewModel 的职能边界 ,得益于 ViewModel 的生命周期更长,我们可以在 activity 重建后将数据传递给 activity ,也可以避免内存泄漏。但是如果不是每次需要就获取数据,而是当每次有新数据时通知我们,应该怎么办?

本文介绍 LiveData ,一个 生命周期感知的,可观察的,数据持有者。同时还会简单分析 LiveData 的源码实现

我们都是 Adapter

在谈 LiveData 前我们来思考一个问题

Android 开发(亦或者说前端开发)的本质工作内容是什么?

对于应用层 app 开发者,开发者的工作主要工作就是 Adapter

什么是 Adapter ,下图可能比较直观

Adapter

图片来自 google image

我们的工作本质是 将数据转换成 UI

数据可能来自网络,来自本地数据库,来自内存,而 UI 可能是 activity 或 fragment。

理想的数据模型

上面我们提到 Android 开发者的核心工作就是将数据转换为 UI 。这个过程比较理想的状态是:当数据发生变化时,UI 跟随变化。我们还可以进一步展开:当 UI 对用户可见时,数据发生变化时 UI 跟随变化;当 UI 对用户不可见时,我们希望数据变化时什么都不做,当 UI 再次对用户可见时根据最新的数据进行 UI 的处理。

LiveData 就是我们理想中的数据模型

LiveData

图片来自 Android Dev Summit '18-Fun with LiveData

LiveData 可以三个关键词概括

  • lifecycle-aware

  • observable

  • data holder

observable

Android 中不同的组件有着不同的生命周期,不同的存活时间

ViewModel

因此我们不会在 ViewModel 中持有 Activity 的引用,因为这会导致当 Activity 重建时内存泄漏,甚至出现空指针的情况

observable

通常我们会在 Activity 中持有 ViewModel 的引用,那么如何进行二者间的通信,如何向 Activity 发送 ViewModel 中的数据?

答案是让 Activity 观察 ViewModel

LiveDataobservable

lifecycle-aware

当观察者观察着某个数据时,该数据必须保留对观察者的引用才能调用它,为了解决这个问题,LiveData 被设计成可感知生命周期

当 activity / fragment 被销毁后,它会自动的取消订阅

data holder

LiveData 仅持有 单个且最新 的数据

data holder

上图中,最右侧是在 ViewModel 中的 LiveData,左侧为观察这个 LiveData 的 activity / fragment 。一旦我们为 LiveData 设值,该值会传递到 activity。简而言之,LiveData 值改变,activity 收到最新的值的变化。但是当观察者不再处于活动状态(STARTED 到 RESUMED ),数据 C 不会被发送到 activity 。当 activity 回到前台,它将收到最新的值,数据 D。LiveData 仅持有单个且最新的数据。当 activity 执行销毁流程时,此时的数据 E 也不会产生任何影响

Transformations

LiveData 提供 两种 transformation ,mapswitch map。开发者也可以创建自定义的 MediatorLiveData

我们都知道 LiveData 可以为 View 和 ViewModel 提供通信,但如果有一个第三方组件(例如 repository )也持有 LiveData。那么它应该如何在 ViewModel 中订阅?该组件并没有 lifecycle

一旦我们的应用愈发复杂,repository 可能会观察数据源

那么 view 如何获取 repository 中的 LiveData

一对一的静态转换(map)

one-to-one static transformation

在上面的示例中,ViewModel 仅将数据从 repository 转发到 view,然后将其转换为 UI Model。 每当 repository 中有新数据时,ViewModel 只需 map

class MainViewModel {
   
  val viewModelResult = Transformations.map(repository.getDataForUser()) {
    data ->
     convertDataToMainUIModel(data)
  }
}

第一个参数为 LiveData 源(来自 repository ),第二个参数是一个转换函数。

// 这里的转换为将 X 转换为 Y
inline fun <X, Y> LiveData<X>.map(crossinline transform: (X) ->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值