一、概念
显示传参 | 局部变量,中间层或底层要使用通过函数形参层层传递,嵌套深耦合高不利于组合的复用。 |
隐式传参 | 全局变量,中间层或底层能直接获取,一处更改处处新值可通过局部改回去解决。 |
二、CompositionLocal
通常情况下,数据以参数形式向下传递给需要的组合,但对于广泛使用的常用数据(颜色形状...)会很麻烦。CompositionLocal 包装的全局变量,局部获取后更改值使用,改动的值出了该作用域失效,其它地方再次调用还是默认值。注意:变量名需要以“Local” 开头。
compositionLocalOf |
值更改后,直接读取的地方会重组,局部修改的不会。 |
staticCompositionLocalOf | 值更改后,所有引用的地方都会重组(不论直接读取还是局部修改),当值几乎不会被更改的时候使用性能更高,因为上面那个会追踪值的读取。 |
CompositionLocalProvider | 提供作用域,修改的值只在该作用域内有效。 |
provides | 用来修改值,可以是函数调用,推荐是中缀调用。 |
current | 取出的值为最近外层所修改的值,外层所有嵌套不存在修改则为默认值。 |
val LocalUser = compositionLocalOf { //编译器会提示变量名应该以“Local”为前缀
User("张三") //默认值,无默认值也可设置错误信息
}
@Composable
fun Show() {
Column {
//CompositionLocalProvider函数提供作用域,provides中缀表达式提供修改,current取出的值为
CompositionLocalProvider(LocalUser provides User("李四")) {
val newUser = LocalUser.current //这里取出的值为外部作用域修改过的
Text(text = newUser.name)
}
val user = LocalUser.current //这里取出的值外部作用域未作修改
Text(text = user.name, fontWeight = FontWeight.Bold)
val color = MaterialTheme.colors.primary //这里取出的值是MaterialDesign提供的
val context = LocalContext.current.resources.getString(R.string.app_name) //获取上下文和资源
}
}
//数据类定义值选择
data class MyColor(
val red: String = "red",
val blue: String = "blue"
)
data class MyFontSize(
val h1: Int = 1,
val h2: Int = 2
)
//单例提供分类选择
object MyDesign {
val LocalMyColor = compositionLocalOf { MyColor() }
val LocalMyFontSize = compositionLocalOf { MyFontSize() }
}
@Composable
fun Show() {
//使用系统提供的
val context = LocalContext.current.resources.getString(R.string.app_name)
//使用自定义的
val myColor = MyDesign.LocalMyColor.current.blue
//修改自定义的
CompositionLocalProvider(MyDesign.LocalMyColor provides MyColor(red = "light red")) {
}
}
}