有小伙伴说看不懂 LiveData、Flow、Channel,跟我走


有小伙伴说看不懂 LiveData、Flow、Channel,跟我走

文章插图
 
你的支持对我意义重大!
Hi , 我是小彭 。本文已收录到 GitHub · Android-NoteBook 中 。这里有 Android 进阶成长路线笔记 & 博客 , 有志同道合的朋友 , 欢迎跟着我一起成长 。(联系方式 & 入群方式在 GitHub)
背景
  • Kotlin Flow 是基于 Kotlin 协程基础能力搭建的一套数据流框架 , 从功能复杂性上看是介于 LiveData 和 RxJAVA 之间的解决方案 。Kotlin Flow 拥有比 LiveData 更丰富的能力 , 但裁剪了 RxJava 大量复杂的操作符 , 做得更加精简 。并且在 Kotlin 协程的加持下 , Kotlin Flow 目前是 google 主推的数据流框架 。
1. 为什么要使用 Flow?LiveData、Kotlin Flow 和 RxJava 三者都属于 可观察的数据容器类 , 观察者模式是它们相同的基本设计模式 , 那么相对于其他两者 , Kotlin Flow 的优势是什么呢?
LiveData 是 androidx 包下的组件 , 是 Android 生态中一个的简单的生命周期感知型容器 。简单即是它的优势 , 也是它的局限 , 当然这些局限性不应该算 LiveData 的缺点 , 因为 LiveData 的设计初衷就是一个简单的数据容器 。对于简单的数据流场景 , 使用 LiveData 完全没有问题 。
  • LiveData 只能在主线程更新数据: 只能在主线程 setValue , 即使 postValue 内部也是切换到主线程执行;
  • LiveData 数据重放问题: 注册新的订阅者 , 会重新收到 LiveData 存储的数据 , 这在有些情况下不符合预期(可以使用自定义的 LiveData 子类 SingleLiveData 或 UnPeekLiveData 解决 , 此处不展开);
  • LiveData 不防抖: 重复 setValue 相同的值 , 订阅者会收到多次 onChanged() 回调(可以使用 distinctUntilChanged() 解决 , 此处不展开);
  • LiveData 不支持背压: 在数据生产速度 > 数据消费速度时 , LiveData 无法正常处理 。比如在子线程大量 postValue 数据但主线程消费跟不上时 , 中间就会有一部分数据被忽略 。
【有小伙伴说看不懂 LiveData、Flow、Channel,跟我走】RxJava 是第三方组织 ReactiveX 开发的组件 , Rx 是一个包括 Java、Go 等语言在内的多语言数据流框架 。功能强大是它的优势 , 支持大量丰富的操作符 , 也支持线程切换和背压 。然而 Rx 的学习门槛过高 , 对开发反而是一种新的负担 , 也会带来误用的风险 。
Kotlin 是 kotlinx 包下的组件 , 不是单纯 Android 生态下的产物 。那么 , Flow 的优势在哪里呢?
  • Flow 支持协程: Flow 基于协程基础能力 , 能够以结构化并发的方式生产和消费数据 , 能够实现线程切换(依靠协程的 Dispatcher);
  • Flow 支持背压: Flow 的子类 SharedFlow 支持配置缓存容量 , 可以应对数据生产速度 > 数据消费速度的情况;
  • Flow 支持数据重放配置: Flow 的子类 SharedFlow 支持配置重放 replay , 能够自定义对新订阅者重放数据的配置;
  • Flow 相对 RxJava 的学习门槛更低: Flow 的功能更精简 , 学习性价比相对更高 。不过 Flow 是基于协程 , 在协程会有一些学习成本 , 但这个应该拆分来看 。
当然 Kotlin Flow 也存在一些局限:
  • Flow 不是生命周期感知型组件: Flow 不是 Android 生态下的产物 , 自然 Flow 是不会关心组件生命周期 。那么我们如何确保订阅者在监听 Flow 数据流时 , 不会在错误的状态更新 View 呢?这个问题在下文 第 6 节再说 。


    推荐阅读