参考资料:https://developer.android.google.cn/jetpack/compose/compositionlocal?hl=zh-cn
什么是CompositionLocal
函数调用的参数传递方式: 显示传参需要层层传递。 隐式传参,定义全局变量。
显示传参
参数需要层层床底比较繁琐
kotlin
/**
* 显式传参
*/
class ExplicitText {
fun Layout() {
var color: String = "black"
//参数需要层层床底比较繁琐
Text(color)
Grid(color)
}
private fun Grid(color: String) {
println("other components in Grid")
Text(color)
}
private fun Text(color: String) {
println(color)
}
}
fun main() {
val ep = ExplicitText()
ep.Layout()
}
隐式传参
隐式传参就是通过定义一个全局变量的方式,在同一作用域下的所有方法都能访问到它,参数直接传递。 但是全局变量带来的问题,一经修改,影响之后被调用的所有参数 如下我们指向改变传给Grid函数的参数的值为“红色”,而不影响之后第二次调用的Text函数。如果使用如下的方式,必然会影响之后被调用的所有参数
kotlin
class ImplicitTest {
var color: String = "黑色"
fun Layout() {
Text()
color="红色"
//全局变量带来的问题,一经修改,影响之后被调用的所有参数
Grid()
Text()
}
private fun Grid() {
println("other components in Grid")
Text()
}
private fun Text() {
println(color)
}
}
fun main() {
val ip = ImplicitTest()
ip.Layout()
}
//输出
黑色
other components in Grid
红色
红色
要解决这个问题,只需要在调用Grid之前修改color的值,在调用完成后再修改回来即可。
kotlin
class ImplicitTest {
var color: String = "黑色"
fun Layout() {
Text()
provider("红色",color){
Grid()
}
Text()
}
fun provider(value:String,perValue: String,content:(()->Unit)){
color=value
content()
color=perValue
}
private fun Grid() {
println("other components in Grid")
Text()
}
private fun Text() {
println(color)
}
}
fun main() {
val ip = ImplicitTest()
ip.Layout()
}
//输出
黑色
other components in Grid
红色
黑色
在Compose中什么情况下会运用到隐式传参呢? 通常情况下,在compose中,数据以参数形式向下流经整个界面树传递给每个可组合函数。但是,对于广泛使用的常用数据(如颜色或类型样式),这可能会很麻烦。 为了支持无需将颜色作为显式参数依赖项传递给大多数可组合项,compose提供了CompositionLocal,可以创建以界面树为作用域的具名对象,这可以用作让数据流经界面树的一种隐式方式。
在主题中的使用
主题就是全局对象,里面的属性,可以被主题对象包裹的所有组件访问和引用,如果要修改某一个组件子树的主题或者属性,就可以使用上面例子中的方法。 而Compose中通过CompositionLocalProvider来为组件属性提供新值
kotlin
@Composable
fun Sample() {
MaterialTheme {
Column {
Text(text = "hello world hello world hello world ")
CompositionLocalProvider(LocalContentColor provides LocalContentColor.current.copy(alpha = 0.73f)) {
Text(text = "hello world hello world hello world ")
Text(text = "hello world hello world hello world ")
CompositionLocalProvider(
LocalContentColor provides LocalContentColor.current.copy(
alpha = 0.37f
)
) {
Text(text = "hello world hello world hello world ")
Text(text = "hello world hello world hello world ")
}
}
}
}
}
上下文Context
组件中的Context也是一个全局变量,不会在组件树中层层传递
kotlin
/**
* Provides a [Context] that can be used by Android applications.
*/
val LocalContext = staticCompositionLocalOf<Context> {
noLocalProvidedFor("LocalContext")
}
例如在任何位置,我们可以获取到上下文,并通过它来获取资源文件。
kotlin
@Composable
fun FruitText(size: Int) {
val resources = LocalContext.current.resources
val text = resources.getString(R.string.app_name)
Text(text = "$size $text")
}
自定义CompositionLocal
实现一个不同卡片海拔高度的卡片层叠布局 首先创建一个卡片的组件 略