Jetpack Compose 中安全地消耗Flow

news2024/11/24 19:48:32

logo

Jetpack Compose 中安全地消耗Flow

以 Lifecycle 为周期的方式收集流是在 Android 上收集流的推荐方式。如果您正在使用 Jetpack Compose 构建 Android 应用程序,则使用 collectAsStateWithLifecycle API 可以在 Lifecycle 为周期的方式下从您的 UI 中收集流。

collectAsStateWithLifecycle 允许您的应用程序在不需要时保存应用程序资源,例如当应用程序在后台时。保持不必要的资源活动可能会影响用户的设备健康状况。这些资源可能包括 Firebase 查询、位置或网络更新以及数据库连接等。

继续阅读了解有关此 API 的更多信息,以及为什么应该以 Lifecycle 为周期的方式进行收集,以及它与 collectAsState API 的比较。

collectAsStateWithLifecycle

collectAsStateWithLifecycle 是一种可组合的函数,可按 Lifecycle 的方式从流中收集值,并将最新值表示为 Compose State。每次发生新的流发射时,此 State 对象的值都会更新。这会导致重组成中的每个 State.value使用。

默认情况下,collectAsStateWithLifecycle 使用 Lifecycle.State.STARTED 来启动和停止从流中收集值。这发生在 Lifecycle 移动到目标状态时的进入和退出之间。这是您可以在 minActiveState 参数中配置的 Lifecycle 状态。

collectAsStateWithLifecycle默认在应用程序在后台时取消流的收集
以下片段演示了如何使用collectAsStateWithLifecycle来收集ViewModel在组合函数中公开的StateFlow的uiState字段:

/* Copyright 2022 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 */

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AuthorRoute(
  onBackClick: () -> Unit,
  modifier: Modifier = Modifier,
  viewModel: AuthorViewModel = hiltViewModel()
) {
  val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()

  AuthorScreen(
    authorState = uiState.authorState,
    newsState = uiState.newsState,
    modifier = modifier,
    onBackClick = onBackClick,
    onFollowClick = viewModel::followAuthorToggle,
  )
}

每当AuthorViewModeluiState发出新的AuthorScreenUiState值时,AuthorRoute都会重新组合。有关collectAsStateWithLifecycle的更多用法,请查看Android应用程序中的Now以及其迁移PR。

要开始在项目中使用collectAsStateWithLifecycle API,请将androidx.lifecycle.lifecycle-runtime-compose构件添加到项目中。

// app/build.gradle file
dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0"
}

在幕后
在幕后,collectAsStateWithLifecycle的实现使用repeatOnLifecycle API,这是使用View系统在Android中收集流的推荐方式。

collectAsStateWithLifecycle可以使你免于编写下面显示的样板代码,该代码也以受生命周期影响的方式从可组合函数中收集流量。

架构中的流式集合

应用程序构架中的类型不应了解其他类型的实现细节。UI 不应该知道 ViewModel 如何生成 UI 状态。如果 UI 在屏幕上不可见,则流式集合应该停止以释放应用程序资源(如果合适)。

UI 可以通过使用 collectAsStateWithLifecycle 收集 UI 状态来帮助释放资源。视图模型可以通过以收集器感知的方式生成 UI 状态来实现相同的功能。如果没有收集器,例如当 UI 在屏幕上不可见时,可以通过在生成 UI 状态时使用.stateIn(WhileSubscribed)流 API 停止来自数据层的上游流。有关此内容的更多信息,请观看“ Kotlin 流实践”系列讲座中的该部分。要测试以此方式生成 UI 状态的视图模型,请查看测试指南。

在 UI 层中,使用 collectAsStateWithLifecycle 消耗 UI 状态,并在数据层公开反应流时使用 .stateIn(WhileSubscribed) 来产生它。这可以使应用程序在不需要时释放资源
流的消费者和生产者不需要知道彼此的实现方式。在具有多个环境、变体、库和功能的大型应用程序中找出实现细节可能非常耗时。更糟糕的是,维护依赖于实现细节的代码很困难。

保持后台资源处于活动状态

Android 应用程序可以在众多 Android 设备上运行。不幸的是,并非所有设备和用户都拥有无尽的资源。应用程序通常在受限环境中运行。当 Android 应用程序运行时,有一些重要因素会影响用户体验和设备系统健康:

  • CPU 使用率:CPU 是所有设备组件中电池消耗最高的。电池寿命是永恒的用户关注点。如果被滥用,用户可能会卸载您的应用程序。
  • 数据使用量:在应用程序未连接到 Wi-Fi 时减少网络流量可以帮助用户节省金钱。
  • 内存使用率:应用程序如何使用内存可以对设备的整体稳定性和性能产生非常大的影响。
    想要尊重用户、设备系统健康或面向亿万用户的 Android 开发人员应根据市场、设备或国家/地区的情况优化这些不同因素。保持不需要的资源处于活动状态可能对所使用的设备和设备运行的 Android 版本类型产生负面影响。在 UI 层中使用 collectAsStateWithLifecycle 可以使层次结构的其余部分释放资源。

collectAsState 对比

开发人员经常会问:如果 collectAsStateWithLifecycle 是从 Android 的 composable 函数中收集 flow 的最安全方式,我们为什么现在还需要 collectAsState API 呢? 或者为什么不将生命周期感知功能添加到 collectAsState 中,而是要创建一个新的 API?

composable 函数的生命周期与运行 Compose 的平台无关。如《composables 生命周期》页面所述,composable 函数的实例进入 Composition、重新计算 0 或多次,最后离开 Composition。

在组合中,可组合函数实例的生命周期
collectAsState API 遵循组合的生命周期。它在可组合函数进入组合时开始收集流,离开组合时停止收集。collectAsState 是跨平台的 API,可用于收集流。

但是,在 Android 应用程序中使用 Compose 时,Android 生命周期也在如何管理资源方面发挥着至关重要的作用。即使在 Android 应用程序处于后台状态时,Compose 停止重新组合,collectAsState 仍保持收集活动。这使得层次结构中的其余部分无法释放资源。

在 Compose 中,collectAsState 和 collectAsStateWithLifecycle 都有其目的。当开发 Android 应用程序时使用后者,当开发其他平台时使用前者。

collectAsState 迁移到 collectAsStateWithLifecycle 是易如反掌的:

/* Copyright 2022 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 */

@Composable
fun AuthorRoute(
    onBackClick: () -> Unit,
    modifier: Modifier = Modifier,
    viewModel: AuthorViewModel = hiltViewModel()
) {

-   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsState()
+   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()

    AuthorScreen(
        authorState = uiState.authorState,
        newsState = uiState.newsState,
        modifier = modifier,
        onBackClick = onBackClick,
        onFollowClick = viewModel::followAuthorToggle,
    )
}

以生命周期感知方式收集流是在Android上收集流的推荐方法,以便允许应用程序中的其他部分在需要时释放资源。

如果您正在使用Jetpack Compose构建Android应用程序,请使用collectAsStateWithLifecycle合成功能执行此操作。

参考

https://github.com/android/nowinandroid
https://developer.android.com/topic/architecture/ui-layer#consume-ui-state

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

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

相关文章

利用Jmeter做接口测试(功能测试)全流程分析

利用Jmeter做接口测试怎么做呢?过程真的是超级简单。 明白了原理以后,把零碎的知识点填充进去就可以了。所以在学习的过程中,不管学什么,我一直都强调的是要循序渐进,和明白原理和逻辑。这篇文章就来介绍一下如何利用…

CP2102 USB转UART国产桥接芯片 DPU02

芯片概述: DPU02是一个高度集成的USB转UART的桥接控制器,该产品提供了一个简单的解决方案,可将RS-232设计更新为USB设计,并简化PCB组件空间。该DPU02包括了一个USB2.0全速功能控制器、USB收发器、振荡器、EEPROM和带有完整调制解调控制信号的…

通过宝塔辅助部署本地Python爬虫项目到阿里云轻量服务器

文章目录 一、 上传项目文件二、准备项目环境2.1、安装 requirements.txt 依赖2.2、安装 node.js 环境2.3、阿里云服务器MySQL 8.0开启远程连接2.4、本地远程连接MySQL测试2.4.1、navicat 远程连接测试2.4.2、python 代码连接测试 笔记:最近想把本地的一套爬虫项目给…

SpringBoot——启动源码(一)

SpringBootApplication注解 前言SpringBootApplicationSpringBootConfigurationEnableAutoConfigurationimport注解 ComponentScan 总结 前言 Springboot作为Spring的脚手架,其本质核心并不提供Spring核心功能,作用就是开发者快速构建,预置三…

怎么转换英文音频成文字?英文音频转文字app分享

两位朋友正在讨论如何将一段英文讲座的音频转换成文字,以便于学习和理解。 Sophia:嗨,我最近听了一段非常精彩的英文讲座,但是对于我来说,理解听到的内容有些困难。你知道有什么方法可以将英文音频转换成文字吗&#…

SpringBoot内置Logback日志的学习

一、日志级别 日志级别有TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF。 TRACE级别最低 DEBUG 的级别低,当需要打印调试信息的话,就用这个级别,不建议在生产环境下使用。 INFO 的级别高一些,当一些重要的信息需要打印的时候&#x…

虹科多功能电流电压采集方案

01电流电压采集基础概念和应用 电流采集、电压采集、电能充电量测试和功率测试在不同领域都有着广泛的应用 ▲汽车电子:电池管理系统BMS、发动机控制系统、车身电子系统 ▲航空航天:飞行控制系统,航空电源管理系统、航空电子设备 ▲消费电…

如何学习和提升使用编程语言的能力? - 易智编译EaseEditing

学习编程语言并提升编程能力需要一定的学习方法和实践。以下是一些方法可以帮助你提升编程语言能力: 学习基本语法: 了解编程语言的基本语法和关键概念。可以通过阅读官方文档、教程、书籍或在线资源来学习。 编写代码: 编写实际的代码是提…

入门孪生网络Siamese Network,我将会分几个博客来逐步阐述我对孪生网络的理解和应用---初步介绍0

文章目录 前言一、孪生网络(Siamese Network)的基本概念二、孪生网络(Siamese Network)的优点三、利用孪生网络进行故障诊断/分类的思路假如我有一堆数据,它可以是轴承故障数值数据,也可以是图像数据,我想进行二分类&a…

ESP32-C2-12模组 AT固件例程

ESP32C2 AT固件使用 ESP32 C2模组,如图1-1所示 图1-1 ESP32 C2模组 ESP32 C2开发板,如图1-2所示 图1-2 ESP32 C2开发 方案亮点 1、完整的 WiFi 子系统,符合 IEEE 802.11b/g/n 协议,具有 Station 模式、SoftAP 模式、SoftAP Stat…

Vue中如何只传递一个人员Name同时把人员Id也传递过去

前言: 根据项目需求,在修改功能中,要求展示一个人员的下拉框,但是又要把人员ID在点击提交时传递过去,一般这种情况有2种解决方法:一是 通过map遍历匹配;二是 在选中人员时将人员ID获取到&#x…

编辑和校对魔法:让文字焕发生机的秘诀

编辑和校对是写作过程中的关键环节,可以让你的文字更加精炼、清晰、引人入胜。以下是一些编辑和校对的秘诀,可以让你的文字焕发生机。 1.保持客观 从读者的角度审视文章,保持客观和中立。确保内容清晰、观点明确,同时避免主观情感…

运筹系列81:LKH代码分析

1. 基本数据结构 基础的node定义在LKH.h中 用于2-level tree的segment定义如下: LKH可以使用3种数据结构,默认是2-level tree: 2-level tree的flip操作(即2-opt算子),在Flip_SL.c中,特殊的地…

请问python如何处理url带有“?”参数的接口?

在Python中处理带有"?"参数的URL接口,可以使用urllib.parse库中的urlencode()函数来进行编码。以下是一些示例代码 如果你想学习自动化测试,我这边给你推荐一套视频,这个视频可以说是B站百万播放全网第一的自动化测试教程&#x…

详解python排序的5种高级用法

来源:投稿 作者:Fairy 编辑:学姐 排序是编程中常用的操作之一。Python提供了多种排序方法,可以适用于不同的排序需求。 那么,今天我们将介绍Python中常用的 5 种列表排序方法。 「1.使用sorted()函数和lambda表达式」…

常见的JS存储方式及其特点

在前端开发中,经常需要在浏览器端存储和管理数据。为了实现数据的持久化存储和方便的访问,JavaScript提供了多种数据存储方式。本文将介绍几种常见的前端JS数据存储方式及其特点。 1. Cookie Cookie是一种小型的文本文件,由浏览器保存在用户…

VMware Workstation下载与安装(适用于在官网注册好账号的朋友,许可证秘钥请自行网上搜索获取)

一、VMware Workstation下载 第一步:点击下方“Resources”链接,进入Vmware官网(本教程适用于已经在官网注册好账号并已经进行登陆的朋友): Resources 第二步:点击“Product Downloads”,进入…

GIT分支管理(随笔)

目录 前言 一、概念原理 1、分支 2、原理 说明1: 说明2: 二、分支操作 1、查看分支 2、创建分支 3、切换分支 4、删除分支 5、合并分支 6、合并冲突 7、重命名分支 8、编制分支的介绍 三、标签 1、概念 2、操作 总结 前言 分支&#xff0…

C语言---关键字static的初步剖析

🚀write in front🚀 📝个人主页:认真写博客的夏目浅石. 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:凡人修C传 💬总结:希望你看完之后&…

数据结构--队列2--双端队列--java双端队列

介绍 双端队列&#xff0c;和前面学的队列和栈的区别在于双端队列2端都可以进行增删&#xff0c;其他2个都是只能一端可以增/删。 实现 链表 因为2端都需要可以操作所以我们使用双向链表 我们也需要一共头节点 所以节点设置 static class Node<E>{E value;Node<E…