Android开发实战班 - 应用架构 - LiveData/Flow 数据流

在 MVVM 架构中,数据流是连接 ViewModel 和 View 的重要桥梁,用于实现数据的观察和响应。Jetpack 提供了两种主要的数据流机制:LiveDataFlow。本章节将深入讲解 LiveData 和 Flow 的概念、使用方法、区别以及在实际开发中的应用场景,帮助学员掌握数据流的应用。

数据流概述

  • 数据流的作用:

    • 数据流用于在 ViewModel 和 View 之间传递数据,实现数据的观察和响应。
    • 数据流可以感知生命周期变化,避免内存泄漏。
  • 数据流的优势:

    • 生命周期感知: 数据流可以感知 View 的生命周期,自动管理订阅和取消订阅,避免内存泄漏。
    • 响应式编程: 数据流采用响应式编程范式,数据变化时自动通知观察者更新 UI。
    • 线程安全: 数据流支持线程切换,可以在不同线程之间安全地传递数据。

11.2 LiveData

LiveData 是 Jetpack 提供的一种可观察的数据持有者类,具有生命周期感知能力。LiveData 适用于需要在 ViewModel 和 View 之间传递数据的场景。

11.2.1 LiveData 的特点
  • 生命周期感知: LiveData 会自动感知 View 的生命周期变化,避免内存泄漏。
  • 自动解绑: 当 View 处于销毁状态时,LiveData 会自动取消订阅。
  • 线程安全: LiveData 可以在主线程或后台线程中更新数据,观察者会在主线程中接收数据更新。
  • 数据持有: LiveData 可以持有数据,并在数据变化时通知观察者。
11.2.2 LiveData 的使用
  • 创建 LiveData:

    class MyViewModel : ViewModel() {private val _data = MutableLiveData<String>()val data: LiveData<String> get() = _datafun updateData(newData: String) {_data.value = newData}
    }
    
  • 观察 LiveData:

    class MyActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)viewModel = ViewModelProvider(this).get(MyViewModel::class.java)viewModel.data.observe(this) { data ->// 更新 UIfindViewById<TextView>(R.id.textView).text = data}// 更新数据viewModel.updateData("Hello, LiveData!")}
    }
    
  • 使用 Transformation:

    • LiveData 提供了 Transformation 类,可以对 LiveData 进行转换,例如 map, switchMap 等。
      val transformedData: LiveData<String> = Transformations.map(data) { originalData ->// 转换数据originalData.toUpperCase()
      }
      
  • 使用 MediatorLiveData:

    • MediatorLiveData 可以合并多个 LiveData 数据源。
      val mediatorLiveData = MediatorLiveData<String>()
      mediatorLiveData.addSource(liveData1) { value ->mediatorLiveData.value = value
      }
      mediatorLiveData.addSource(liveData2) { value ->mediatorLiveData.value = value
      }
      
11.2.3 LiveData 的优点和缺点
  • 优点:

    • 简单易用,易于上手。
    • 生命周期感知,避免内存泄漏。
    • 线程安全。
  • 缺点:

    • 功能相对有限,缺乏复杂的操作符。
    • 不支持背压(backpressure)。

11.3 Flow

Flow 是 Kotlin 协程提供的一种异步数据流机制,适用于需要复杂数据处理的场景。Flow 提供了丰富的操作符,可以对数据进行转换、过滤、合并等操作。

11.3.1 Flow 的特点
  • 异步处理: Flow 是异步的,可以在不同的协程中处理数据。
  • 丰富的操作符: Flow 提供了丰富的操作符,例如 map, filter, flatMap, zip 等。
  • 背压支持: Flow 支持背压,可以处理数据流中的数据积压问题。
  • 协程支持: Flow 依赖于 Kotlin 协程,可以与协程的其他功能无缝集成。
11.3.2 Flow 的使用
  • 创建 Flow:

    class MyViewModel : ViewModel() {private val _dataFlow = MutableStateFlow<String>("")val dataFlow: StateFlow<String> get() = _dataFlowfun updateData(newData: String) {_dataFlow.value = newData}
    }
    
  • 观察 Flow:

    class MyActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)viewModel = ViewModelProvider(this).get(MyViewModel::class.java)lifecycleScope.launch {viewModel.dataFlow.collect { data ->// 更新 UIfindViewById<TextView>(R.id.textView).text = data}}// 更新数据viewModel.updateData("Hello, Flow!")}
    }
    
  • 使用操作符:

    • Flow 提供了丰富的操作符,可以对数据进行转换、过滤、合并等操作。
      val transformedFlow: Flow<String> = dataFlow.map { originalData ->// 转换数据originalData.toUpperCase()
      }val filteredFlow: Flow<String> = dataFlow.filter { data ->// 过滤数据data.isNotEmpty()
      }
      
  • 使用 CoroutineScope:

    • Flow 的观察需要在协程中进行,可以使用 lifecycleScopeviewModelScope 来管理协程生命周期。
      lifecycleScope.launch {viewModel.dataFlow.collect { data ->// 更新 UI}
      }
      
11.3.3 LiveData 与 Flow 的比较
  • 生命周期感知:

    • LiveData 内置生命周期感知能力,而 Flow 需要手动管理生命周期。
    • 可以使用 lifecycleScopeviewModelScope 来管理 Flow 的生命周期。
  • 数据处理:

    • Flow 提供了丰富的操作符,可以进行复杂的数据处理。
    • LiveData 的操作符相对有限。
  • 线程支持:

    • LiveData 主要在主线程中更新数据。
    • Flow 支持在不同的协程中处理数据,可以更灵活地进行线程切换。
  • 背压支持:

    • Flow 支持背压,可以处理数据流中的数据积压问题。
    • LiveData 不支持背压。
11.3.4 Flow 在 Jetpack Compose 中的应用

在 Jetpack Compose 中,可以使用 collectAsState 函数将 Flow 转换为 Compose 的 State,从而实现数据驱动 UI。

  • 示例:

    @Composable
    fun MyComposable(viewModel: MyViewModel) {val data by viewModel.dataFlow.collectAsState()Text(text = data)
    }
    
  • 完整示例:

    class MyViewModel : ViewModel() {private val _dataFlow = MutableStateFlow<String>("")val dataFlow: StateFlow<String> get() = _dataFlowfun updateData(newData: String) {_dataFlow.value = newData}
    }@Composable
    fun MyComposable(viewModel: MyViewModel) {val data by viewModel.dataFlow.collectAsState()Column {Text(text = data)Button(onClick = { viewModel.updateData("Hello, Flow!") }) {Text(text = "Update Data")}}
    }
    

11.4 实战案例

  1. 案例一:使用 LiveData 实现简单的计数器应用

    • 创建一个 ViewModel,使用 LiveData 存储计数器的值。
    • 在 Activity 中观察 LiveData,更新 UI。
    • 创建一个按钮,点击按钮更新计数器的值。
  2. 案例二:使用 Flow 实现图片浏览应用

    • 创建一个 ViewModel,使用 Flow 存储图片列表。
    • 在 Jetpack Compose Composable 中使用 collectAsState 观察 Flow,更新 UI。
    • 创建一个按钮,点击按钮加载图片列表。

11.5 课后作业

  1. 任务一:使用 LiveData 实现用户列表应用

  2. 任务二:使用 Flow 实现图片浏览应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rk3399开发环境使用Android 10初体验蓝牙功能

版本 日期 作者 变更表述 1.0 2024/11/10 于忠军 文档创建 零. 前言 由于Bluedroid的介绍文档有限&#xff0c;以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等)&#xff0c;加上需要掌握的语言包括Java/C/C等&#xff0…

python脚本实现csv中百度经纬度转84经纬度

数据准备 csv文件,带百度经纬度字段:bd09_x,bd09_y 目的 将百度经纬度转换为84经纬度,并在csv文件中添加两个字段:84_x,84_y python脚本 from ChangeCoordinate import ChangeCoordimport pandas as pd import numpy as npcoord = ChangeCoord()def bd09_to_wgs84

前端反向代理的配置和實現

反向代理是位於客戶端和服務器之間的一個中間層&#xff0c;它代表客戶端向伺服器發起請求&#xff0c;然後將伺服器的回應返回給客戶端。與傳統的正向代理不同&#xff0c;反向代理是由伺服器端配置的&#xff0c;客戶端通常不知道它的存在。在前端開發中&#xff0c;反向代理…

微调Helsinki-NLP-en-zh模型

Helsinki-NLP 是一个广泛使用的开源机器翻译&#xff08;Machine Translation&#xff0c;MT&#xff09;模型系列&#xff0c;基于 Marian NMT 框架 Hugggingface地址&#xff1a;https://huggingface.co/Helsinki-NLP/opus-mt-en-zh 原本的模型对于国内外公司的名称支持度很…

C++中的初始化列表

初始化参数列表 用于在构造函数中初始化类的数据成员。 语法&#xff1a;构造函数&#xff08;&#xff09;&#xff1a;属性1&#xff08;值1&#xff09;&#xff0c;属性2&#xff08;值2&#xff09;......{ } 性质&#xff1a; 1.只能在构造函数中使用 2.引用 或 常量…

QT基本绘图

QT绘图 1.概述 这篇文章介绍如何绘图 2.绘图基本操作 创建一个普通的widget类型的项目 在widget.h 文件中重写绘图事件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : p…

【IEEE独立出版 |往届均已成功检索】第八届大数据与应用统计国际学术研讨会(ISBDAS 2025)

重要信息 时间地点&#xff1a;2025年2月28日-3月2日 中国 广州 会议检索&#xff1a;EI Compendex, Scopus →点此投稿/参会/了解会议详情 组织单位 主办单位&#xff1a;广东省高等教育学会人工智能与高等教育研究分会 协办单位&#xff1a;北京师范大学人工智能与未…

C# 中的 LINQ:轻松处理集合和数据

C#中的LINQ&#xff08;Language Integrated Query&#xff09;&#xff0c;这是一个非常强大且实用的功能&#xff0c;可以简化集合操作和数据查询。以下是一篇关于C#中LINQ使用的文章。 引言 LINQ&#xff08;Language Integrated Query&#xff09;是C#语言的一个重要特性…

自动化立体仓库:详解

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载。 自动化立体仓库&#xff08;Automated S…

Hash table类算法【leetcode】

哈希表中关键码就是数组的索引下标&#xff0c;然后通过下标直接访问数组中的元素 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用来快速判断一个元素是否出现集合里。 例如要查询一个名字是否在这所学校里。 要枚举的话时间复杂度是O(n)&#xff0c;但如果使用哈希…

window 中安装 php 环境

window 中安装 php 环境 一、准备二、下载三、安装四、测试 一、准备 安装前需要安装 Apache &#xff0c;可以查看这篇博客。 二、下载 先到这里下载 这里选择版本为“VS16 x64 Thread Safe”&#xff0c;这个版本不要选择线程安全的&#xff0c;我试过&#xff0c;会缺少文…

Kubernetes部署Grafana详细教程

1. 概述 Grafana是一个强大的开源监控和可视化工具,可以帮助我们更好地理解和分析系统性能数据。在Kubernetes环境中部署Grafana可以让我们更方便地监控集群和应用的状态。 2. 准备工作 一个正常运行的Kubernetes集群kubectl命令行工具,已配置可以访问您的集群集群中已创建名…

嵌入式Linux学习之Linux基础再过部分——文件IO(1)

目录 先来看看Linux是如何操作文件IO的 文件描述符 打开文件open pathname flags mode 返回值 write 参数详解 返回值 在哪里你能使用write flags read 返回值 flags close lseek whence 参数常量 返回值 示例 1 示例 2 demo3 深入探究文件IO Linux 系统…

LeetCode 209 长度最小的子数组(滑动窗口)

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode 209 长度最小的子数组(滑动窗口) 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于…

C# 高级--反射 详解

一、反射是什么 1、C#编译运行过程 高级语言->编译->dll/exe文件->CLR/JIT->机器码 2、原理解析metadata&#xff1a;元数据数据清单&#xff0c;记录了dll中包含了哪些东西,是一个描述。IL&#xff1a;中间语言&#xff0c;编译把高级语言编译后得到的C#中最真…

【Web前端】Web API:构建Web应用核心

什么是 API API&#xff08;应用程序编程接口&#xff09;是一组定义了软件组件之间如何交互的规则和协议。它允许一个程序调用另一个程序的功能&#xff0c;而不用了解其内部实现细节。 Web 开发中&#xff0c;API 通常用于实现前端与后端之间的通信。 客户端 JavaScript 中的…

Telegram bot Mini-App开发实践---Telegram简单介绍与初始化小程序获取window.Telegram.WebApp对象并解析

➡️【好看的灵魂千篇一律,有趣的鲲志一百六七!】- 欢迎认识我~~ 作者:鲲志说 (公众号、B站同名,视频号:鲲志说996) 科技博主:极星会 星辉大使 后端研发:java、go、python、TS,前电商、现web3 主理人:COC杭州开发者社区主理人 、周周黑客松杭州主理人、 AI爱好…

VRT: 关于视频修复的模型

VRT: 关于视频修复的模型 1. 视频修复的背景与重要性背景介绍&#xff1a;重要性&#xff1a; 2. VRT的重要性和研究背景VRT的背景&#xff1a;VRT的重要性&#xff1a; 3. 视频修复概述3.1 定义与目标3.2 与单图像修复的区别3.3 对时间信息利用的需求 4. VRT模型详解4.1 整体框…

【linux】ubuntu下常用快捷键【笔记】

环境 硬件&#xff1a;通用PC 系统&#xff1a;Ubuntu 20.04 软件 &#xff1a; 打开终端窗口&#xff1a;Ctrl Alt T 关闭当前窗口&#xff1a;Alt F4 改变窗口大小&#xff1a;Alt F8 移动窗口&#xff1a; Alt F7 配合 “←”、“→”、“↑”、“↓”来移动窗口 …

java 增强型for循环 详解

Java 增强型 for 循环&#xff08;Enhanced for Loop&#xff09;详解 增强型 for 循环&#xff08;也称为 “for-each” 循环&#xff09;是 Java 从 JDK 5 开始引入的一种便捷循环语法&#xff0c;旨在简化对数组或集合类的迭代操作。 1. 基本语法 语法格式 for (类型 变量…