当前位置: 首页 > news >正文

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.lryc.cn/news/601053.html

相关文章:

  • VS Code + LaTeX 绘制电气图完全指南(含 PlantUML 样式参考)
  • 酒店智能门锁SDK新V门锁系统接口函数[2025版]Delphi 7.0——东方仙盟硬件接口库
  • 方正小标宋简3.0,可编辑
  • Python - 100天从新手到大师 - Day6
  • 【科研绘图系列】R语言绘制误差连线散点图
  • freeRTOS 静态创建任务
  • FastAPI入门:安装、Pydantic、并发和并行
  • Day04–链表–24. 两两交换链表中的节点,19. 删除链表的倒数第 N 个结点,面试题 02.07. 链表相交,142. 环形链表 II
  • TCP如何解决网络切换问题
  • Java模块化编程深度指南:从过程式到面向对象的进化之路
  • JavaSE:初识数组
  • 小架构step系列26:Spring提供的validator
  • 详细介绍MySQL的索引类型
  • Maven之依赖管理
  • 基于tk界面库的扩展类
  • 网络:基础概念
  • nacos启动报错:Unable to start embedded Tomcat。
  • 基于POD和DMD的压气机叶片瞬态流场分析与神经网络预测
  • iview: 对输入框进行Poptip 换行提示
  • 【Redis】 Redis 基础命令和原理
  • 从治理到共情——平台伦理的乡村共建之路
  • 数据空间技术在智慧水库管理平台中的赋能
  • 每日面试题15:如何解决堆溢出?
  • 2.JVM跨平台原理(字节码机制)
  • 嵌入式硬件篇---zigbee无线串口通信问题解决方法
  • 【6G新技术探索】AG-UI(Agent User Interaction Protocol) 协议介绍
  • 大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(1):总体介绍
  • 设计模式十一:享元模式(Flyweight Pattern)
  • 融合为体,AI为用:数据库在智能时代的破局之道
  • 快速入门Linux操作系统(一)