文章目录为什么需要 CompositionLocal核心概念与创建方式示例适用场景CompositionLocal 是 Jetpack Compose 中一个非常重要的机制它允许你在组合树中隐式地向下传递数据而不需要通过每个 Composable 函数的参数手动传递为什么需要 CompositionLocal在 Compose 中通常通过参数将数据传递给子函数。但在复杂的应用中某些数据如主题颜色、字体样式、当前登录用户信息或配置信息几乎每个 UI 组件都需要访问。如果通过参数层层传递代码冗余中间层的函数即使不需要这些数据也必须定义参数并向下转发。难以维护一旦需要增加一个全局参数可能需要修改数十个函数的签名。CompositionLocal 解决了这个问题你在高层提供一个值底层的任何 Composable 都可以直接访问它。核心概念与创建方式创建 CompositionLocal 主要有两种方式A.compositionLocalOf特性当提供的值发生改变时Compose 只会让读取该值的 Composable 发生重组。B.staticCompositionLocalOf特性当值改变时Compose 会重新读取并重组整个内容树而不是只重组读取它的部分。优点存储和读取的性能比 compositionLocalOf 略好因为它不需要跟踪依赖关系。重要属性currentclassCompositionLocal{publicinlinevalcurrent:TReadOnlyComposableComposableget()currentComposer.consume(this)}示例dataclassUserInfo(valname:String,valisAdmin:Boolean)valLocalUserInfocompositionLocalOf{UserInfo(default,false)}// val LocalUserInfo staticCompositionLocalOf { UserInfo(default, false) }ComposablefunCompLocalTest(){// state 记忆varcurrentUserbyremember{mutableStateOf(UserInfo(Manager,true))}// 通过 CompositionLocalProvider 向下传递本质是定义了共享它的作用域CompositionLocalProvider(LocalUserInfo provides currentUser){// 这里的子组件及其所有后代都可以访问到 currentUserDashboard1()Dashboard2()// 内部使用 local.current}valuserLocalUserInfo.currentText(texthi,${user.name}! Admin:${user.isAdmin},modifierModifier.padding(top40.dp))Button(onClick{currentUserUserInfo(xx,false)},modifierModifier.padding(top100.dp)){Text(change user${currentUser})}}ComposableprivatefunDashboard1(){SideEffect{Log.d(Dashboard1,Dashboard1: 进入组合)}}ComposableprivatefunDashboard2(){SideEffect{Log.d(Dashboard2,Dashboard2: 进入组合)}UserInfoLabel()}ComposableprivatefunUserInfoLabel(){SideEffect{Log.d(UserInfoLabel,UserInfoLabel: 进入组合)}// 获取当前作用域内的值valuserLocalUserInfo.currentText(textWelcome,${user.name}! Admin:${user.isAdmin})}通过compositionLocalOf或staticCompositionLocalOf创建的类型它的直接或间接父类 是ProvidableCompositionLocal这个父类中提供了一个 中缀函数:publicinfixfunprovides(value:T):ProvidedValueTdefaultProvidedValue(value)CompositionLocalProvider函数接收一个ProvidedValue*类型的参数publicfunCompositionLocalProvider(value:ProvidedValue*,content:Composable()-Unit){currentComposer.startProvider(value)content()currentComposer.endProvider()}这个参数类型就是上面的中缀函数的返回类型SideEffect每次进入组合阶段时都会调用。重组当然也会。CompLocalTest() 功能currentUser 声明定义成 记忆状态使用了remember { mutableStateOf(...) }CompositionLocalProvider向内部 content 传递了 currentUser界面中 第一个组件是text Welcome ...用户name是 “xx”第二个 padding(top 40.dp) 的Text显示的是 默认用户name是 “default”第三个组件按钮 padding(top 100.dp)显示的是 用户name是 “Manager”Button 点击修改了 记忆状态对象 currentUser引起了读取 currentUser 的可组合项发生重组。Button中的Text(change user${currentUser})、UserInfoLabel 中的text Welcome ...肯定会发生重组若使用... compositionLocalOf {}点击后只有这两处会发生重组。此时日志输出UserInfoLabel: 进入组合若使用... staticCompositionLocalOf {}点击后不光这两处会发生重组CompositionLocalProvider的 content 内的 所有可组合项包括子项都会重组。此时日志输出:Dashboard1: 进入组合Dashboard2: 进入组合UserInfoLabel: 进入组合适用场景compositionLocalOf需要局部灵活变动、且变动频繁的数据。staticCompositionLocalOf需要局部灵活变动、但几乎一成不变的数据如皮肤、样式