Compose笔记(三十八)--CompositionLocal

        这一节主要了解一下CompositionLocal,CompositionLocal是Jetpack Compose中用于组件树内隐式数据传递的核心机制,其设计初衷是解决跨多层组件的数据共享问题,避免通过函数参数逐层传递数据。简单总结:

API:
(1)compositionLocalOf<T>
创建一个动态的CompositionLocal实例,当值变化时,仅触发读取该值的组件重组。
(2)staticCompositionLocalOf<T>
创建一个静态的CompositionLocal实例,值变化时触发整个作用域内所有组件重组。 
(3)CompositionLocalProvider
为子组件树提供CompositionLocal的值,作用域仅限于其内容块。 
场景:
1. 主题与样式配置,最常见的场景是传递应用主题信息(颜色、字体、间距等),让组件树中的所有子组件都能访问统一的样式配置。
2. 上下文信息传递,替代传统Android中的Context传递,在Compose组件树中共享上下文相关数据。 
3. 用户状态与全局配置,共享用户信息(如登录状态、权限)或全局配置,让深层嵌套的组件也能访问这些状态。
4. 工具类与服务共享,传递工具类实例或服务,避免在每个组件中单独初始化。

栗子:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.spprivate val LocalAppTheme = compositionLocalOf<AppTheme> {error("No AppTheme provided")
}data class AppTheme(val primaryColor: Color,val textColor: Color,val fontSize: Float
)@Composable
fun ThemeProvider(theme: AppTheme = AppTheme(primaryColor = Color.Blue,textColor = Color.White,fontSize = 16f),content: @Composable () -> Unit
) {CompositionLocalProvider(LocalAppTheme provides theme) {content()}
}@Composable
fun ThemedText(text: String) {val theme = LocalAppTheme.currentText(text = text,color = theme.textColor,fontSize =18.sp)
}@Composable
fun CompositionLocalExample() {ThemeProvider {Box(modifier = Modifier.fillMaxSize().background(LocalAppTheme.current.primaryColor),contentAlignment = Alignment.Center) {ThemedText("Hello CompositionLocal!")}}
}
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifierdata class PermissionState(val cameraGranted: Boolean,val locationGranted: Boolean,val storageGranted: Boolean,val requestCamera: () -> Unit,val requestLocation: () -> Unit,val requestStorage: () -> Unit
)private val LocalPermissions = compositionLocalOf<PermissionState> {error("No PermissionState provided. Make sure to wrap your content with PermissionProvider.")
}@Composable
fun PermissionProvider(content: @Composable () -> Unit
) {var cameraGranted by remember { mutableStateOf(false) }var locationGranted by remember { mutableStateOf(false) }var storageGranted by remember { mutableStateOf(false) }val permissionState = PermissionState(cameraGranted = cameraGranted,locationGranted = locationGranted,storageGranted = storageGranted,requestCamera = { cameraGranted = true },  // 实际会调用真实的权限请求API,只是演示requestLocation = { locationGranted = true },requestStorage = { storageGranted = true })CompositionLocalProvider(LocalPermissions provides permissionState) {content()}
}@Composable
fun CameraFeature() {val permissions = LocalPermissions.currentColumn(horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center) {Text("相机功能")if (permissions.cameraGranted) {Text("✅ 相机权限已授予")Button(onClick = { /* 使用相机的逻辑 */ }) {Text("拍照")}} else {Text("❌ 相机权限未授予")Button(onClick = permissions.requestCamera) {Text("请求相机权限")}}}
}@Composable
fun LocationFeature() {val permissions = LocalPermissions.currentColumn(horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center) {Text("位置功能")if (permissions.locationGranted) {Text("✅ 位置权限已授予")Button(onClick = { /* 使用位置的逻辑 */ }) {Text("获取当前位置")}} else {Text("❌ 位置权限未授予")Button(onClick = permissions.requestLocation) {Text("请求位置权限")}}}
}@Composable
fun FeaturesScreen() {Column(modifier = Modifier.fillMaxSize(),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.SpaceEvenly) {Text("应用功能", style = androidx.compose.material3.MaterialTheme.typography.headlineMedium)CameraFeature()LocationFeature()}
}@Composable
fun PermissionTest() {    PermissionProvider {FeaturesScreen()}
}

注意
避免滥用:CompositionLocal适合共享“全局/半全局”数据,若数据仅在少数几层传递,直接用参数传递更清晰。
明确作用域:通过 CompositionLocalProvider限制数据的生效范围,避免全局污染。
性能考量:CompositionLocal的值变化会导致依赖它的所有组件重组,不宜用于频繁变化的数据。

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

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

相关文章

解决uniapp 使用uview生成小程序包太大无法上传的问题

直接打包的插件内容优化后完美上传&#xff0c; 相信眼尖的小伙伴已经发现了问题的关键 uview 会在每个组件里重复引css。导致包太大。 并且 它的格式是 data-v-哈希 没法简单的处理 需要压缩通用规则。然后 再引用压缩后的规则例如是然后 成功上传

在线工具+网页平台来学习和操作Python与Excel相关技能

&#x1f517;一、在线平台推荐&#xff08;免安装&#xff09; ✅Python平台&#xff08;直接写代码、跑结果&#xff09;&#xff1a; 平台 优点 地址 Google Colab 免费&#xff0c;支持图表和文件操作&#xff0c;最推荐 https://colab.research.google.com …

R Excel 文件处理指南

R Excel 文件处理指南 引言 R语言作为一种强大的统计计算和图形展示工具&#xff0c;在数据分析领域有着广泛的应用。而Excel作为办公软件的佼佼者&#xff0c;在数据记录和计算中也扮演着重要的角色。本文旨在介绍如何使用R语言处理Excel文件&#xff0c;包括读取、写入以及数…

亿级流量短剧平台架构演进:高并发场景下的微服务设计与性能调优

一、短剧系统概述与市场背景短剧作为一种新兴的内容形式&#xff0c;近年来在移动互联网领域迅速崛起。根据最新市场数据显示&#xff0c;2023年中国短剧市场规模已突破300亿元&#xff0c;用户规模达到4.5亿&#xff0c;平均每日观看时长超过60分钟。这种爆发式增长催生了对专…

4G手机控车模块的核心功能与应用价值

4G手机控车模块是基于4G无线通信技术实现车辆远程监控、控制及数据交互的嵌入式设备。其核心功能包括通过4G网络实现高速数据传输&#xff08;支持TCP/IP协议&#xff09;、远程参数配置与设备管理、多网络制式兼容&#xff0c;集成GPS/北斗定位功能&#xff0c;可实时获取车辆…

【leetGPU】1. Vector Addition

问题 link: https://leetgpu.com/challenges/vector-addition Implement a program that performs element-wise addition of two vectors containing 32-bit floating point numbers on a GPU. The program should take two input vectors of equal length and produce a si…

瑞吉外卖学习笔记

TableField 作用: 当数据库中表的列名与实体类中的属性名不一致&#xff0c;使用TableField 使其对应 TableField("db_column_name") private String entityFieldName;exist 属性 : 指定该字段是否参与增删改查操作。 TableField(exist false) private String tempF…

RoPE:相对位置编码的旋转革命——原理、演进与大模型应用全景

“以复数旋转解锁位置关系的本质表达&#xff0c;让Transformer突破长度藩篱” 旋转位置编码&#xff08;Rotary Position Embedding, RoPE&#xff09; 是由 Jianlin Su 等研究者 于2021年提出的突破性位置编码方法&#xff0c;通过复数空间中的旋转操作将相对位置信息融入Tra…

震网(Stuxnet):打开潘多拉魔盒的数字幽灵

在科技飞速发展的今天&#xff0c;代码和数据似乎只存在于无形的数字世界。但如果我告诉大家&#xff0c;一段代码曾悄无声息地潜入一座受到严密物理隔离的核工厂&#xff0c;并成功摧毁了其中的物理设备&#xff0c;大家是否会感到一丝寒意&#xff1f;这不是科幻电影的情节&a…

一文读懂:到底什么是 “具身智能” ?

今天咱们来好好聊聊一个最近很火的一个技术话题——具身智能&#xff01; 这个词听起来是不是有点难懂&#xff1f;其实我们可以简单理解为&#xff1a;具身智能是具有身体的人工智能体。这样是不是会容易理解一些&#xff1f; 具身智能&#xff08;Embodied Intelligence&…

企业级区块链平台Hyperchain核心原理剖析

Hyperchain作为国产自主可控的企业级联盟区块链平台&#xff0c;其核心原理围绕高性能共识、隐私保护、智能合约引擎及可扩展架构展开&#xff0c;通过多模块协同实现企业级区块链网络的高效部署与安全运行。 以下从核心架构、关键技术、性能优化、安全机制、应用场景五个维度展…

论文阅读-RaftStereo

文章目录1 概述2 模块说明2.1 特征抽取器2.2 相关金字塔2.3 多级更新算子2.4 Slow-Fast GRU2.5 监督3 效果1 概述 在双目立体匹配中&#xff0c;基于迭代的模型是一种比较主流的方法&#xff0c;而其鼻祖就是本文要讲的RaftStereo。 先来说下什么是双目立体匹配。给定极线矫正…

内存优化:从堆分配到零拷贝的终极重构

引言 在现代高性能软件开发中&#xff0c;内存管理往往是性能优化的关键战场。频繁的堆内存分配(new/delete)不仅会导致性能下降&#xff0c;还会引发内存碎片化问题&#xff0c;严重影响系统稳定性。本文将深入剖析高频调用模块中堆分配泛滥导致的性能塌方问题&#xff0c;并…

【GoLang#2】:基础入门(工具链 | 基础语法 | 内置函数)

前言&#xff1a;Go 的一些必备知识 1. Go 语言命名 Go的函数、变量、常量、自定义类型、包(package)的命名方式遵循以下规则&#xff1a; 首字符可以是任意的Unicode字符或者下划线剩余字符可以是Unicode字符、下划线、数字字符长度不限 Go 语言代码风格及开发事项代码每一行结…

Bert项目--新闻标题文本分类

目录 技术细节 1、下载模型 2、config文件 3、BERT 文本分类数据预处理流程 4、对输入文本进行分类 5、计算模型的分类性能指标 6、模型训练 7、基于BERT的文本分类预测接口 问题总结 技术细节 1、下载模型 文件名称--a0_download_model.py 使用 ModelScope 库从模型仓…

sendfile系统调用及示例

好的&#xff0c;我们继续学习 Linux 系统编程中的重要函数。这次我们介绍 sendfile 函数&#xff0c;它是一个高效的系统调用&#xff0c;用于在两个文件描述符之间直接传输数据&#xff0c;通常用于将文件内容发送到网络套接字&#xff0c;而无需将数据从内核空间复制到用户空…

数据结构习题--删除排序数组中的重复项

数据结构习题–删除排序数组中的重复项 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 方法&…

Docker的容器设置随Docker的启动而启动

原因也比较简单&#xff0c;在docker run 的时候没有设置–restartalways参数。 容器启动时&#xff0c;需要增加参数 –restartalways no - 容器退出时&#xff0c;不重启容器&#xff1b; on-failure - 只有在非0状态退出时才从新启动容器&#xff1b; always - 无论退出状态…

JWT安全机制与最佳实践详解

JWT&#xff08;JSON Web Token&#xff09; 是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在各方之间安全地传输信息作为紧凑且自包含的 JSON 对象。它被广泛用于身份验证&#xff08;Authentication&#xff09;和授权&#xff08;Authorization&#xff…

如何解决pip安装报错ModuleNotFoundError: No module named ‘ipython’问题

【Python系列Bug修复PyCharm控制台pip install报错】如何解决pip安装报错ModuleNotFoundError: No module named ‘ipython’问题 摘要 在开发过程中&#xff0c;我们常常会遇到pip install报错的问题&#xff0c;其中一个常见的报错是 ModuleNotFoundError: No module named…