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

news/2024/11/25 10:56:33/

在 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.ppmy.cn/news/1549799.html

相关文章

Claude Opus MetaPrompt 系统详解

Claude Opus MetaPrompt 系统详解 简介 MetaPrompt系统是由Anthropic提出的&#xff0c;旨在帮助用户为AI助手Claude生成高质量的提示。它指导用户定义任务和变量、结构化指令和细化输出。 具体内容 特点 主要针对Claude 3 Opus版本&#xff0c;并且适用于单轮对话。 核心…

windows C#-生成和使用异步流(上)

异步流建立流式处理数据源模型。 数据流经常异步检索或生成元素。 它们为异步流式处理数据源提供了自然编程模型。 先决条件 需要将计算机设置为运行 .NET&#xff0c;包括 C# 编译器。 C# 编译器随附于 Visual Studio 2022 或 .NET SDK。 将需要创建 GitHub 访问令牌&#…

[系统安全]PE文件头中的重定位表

PE加载的过程 任何一个EXE程序会被分配4GB的内存空间&#xff0c;用户层处理低2G的内存&#xff0c;驱动处理高2G的内存。 1、双击EXE程序&#xff0c;操作系统开辟一个4GB的空间。2、从ImageBase决定了加载后的基址&#xff0c;ImageSize决定了程序有多大。3、然后加载DLL 大…

Python Flask快速开发网站

在Web开发领域,Python拥有多种优秀的Web框架,例如Django、Flask、Pyramid等。其中Flask是一个微型框架,核心代码非常精简,只包含了Web应用最基本的功能。这使得Flask非常轻量级,容易上手,适合快速开发小型Web应用。本文将介绍如何使用Flask快速搭建一个简单的网站。 © ivw…

[2024.11.17-24] 一周科技速报

2024 世界青年科学家峰会全体大会 时间地点&#xff1a;11 月 17 日在浙江温州举行。 参会人员&#xff1a;吸引了来自 71 个国家和地区以及 63 个国际科技组织的近 800 名科学家、企业家、教育家和青年科技人才代表。 会议内容&#xff1a;以 “汇聚天下英才共创美好未来”…

云计算期中作业:Spark机器学习问题解决

在原有pdf教程教程上&#xff0c;做一个补充 idea内搭建环境 导入依赖 就直接利用之前的作业工程项目里直接写&#xff0c;所以依赖基本上不用再导入了&#xff0c;如果要导入&#xff0c;看自己依赖的版本号&#xff0c;不要直接复制教程&#xff0c;比如我的&#xff1a; …

Java 8 Stream API 在数据转换中的应用 —— 将列表转换为映射

文章目录 背景原因1. 数据库设计或约束问题2. 业务逻辑问题3. 测试数据4. 数据库同步问题5. 编程错误 如何避免和处理键冲突1. 数据库层面2. 业务逻辑层面3. 测试数据管理4. 代码层面示例代码 总结 背景 本文实际生产案例讲解配套文章&#xff1a;sysUserList 中为何会出现多个…

NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案

EasyNVR是基于端-边-云一体化架构的安防监控视频融合云平台&#xff0c;具有简单轻量的部署方式与多样的功能&#xff0c;支持多种协议&#xff08;如GB28181、RTSP、Onvif、RTMP&#xff09;和设备类型&#xff08;IPC、NVR等&#xff09;&#xff0c;提供视频直播、录像、回放…