Compose(1/N) - 概念 基本使用
一、概念
1.1 解决的问题
APP展示的数据绝大多数不是静态数据而是会实时更新,传统的命令式UI写法更新界面繁琐且容易同步错误。
1.2 Compose优势
- 由一个个可组合的Composable函数(可看作是一个Layout布局)拼成界面,方便维护和复用。
- 布局模型不允许多次测量。
- Compose可以和View互操作(相互包含对方)。
1.3 声明式UI
Compose会对界面用到的数据自动进行订阅(属性委托),当数据变化时界面会自动更新。(同为数据和界面关联,databinding只能更新组件的值,Compose可以控制组件是否显示)
声明式UI | 只需要把界面写出来,不需要再手动写代码去刷新。 |
命令式UI | xml写的界面,当数据变了就需要Java/Kotlin手动(命令指挥)刷新,即 findViewById( ) 拿到控件再 setText( ) 设置数据。 |
1.4 重组
可理解为重绘。当数据发生改变时,对应的Composable函数可以再次被调用来重绘,但局部节点的变化不应让整个UI全部重绘。Compose首先会生成整个屏幕,然后仅执行必要的更改。(
由于其它函数可能被跳过,因此避免使用共享数据搞附带效应)
二、基本使用
2.1 添加依赖
查看官方最新版本
兼容性对应关系
最低版本:Kotlin ≥ 1.5.10、Android ≥ 5.0(API21)、AndroidStudio ≥ Arctic Fox 2020.3.1。
android {
buildFeatures {
compose true //启用Compose功能
}
composeOptions {
//见上方链接,此处定义的Kotlin编译器扩展版本需要对应兼容的Kotlin版本
kotlinCompilerExtensionVersion = "1.4.2"
}
}
implementation "androidx.compose.compiler:compiler:1.4.3"
implementation 'androidx.activity:activity-compose:1.6.1' //与activity结合使用
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1' //与viewModel结合使用
implementation 'androidx.compose.runtime:runtime-livedata' //与liveData结合使用
implementation 'androidx.compose.ui:ui-tooling-preview:1.1.1' //AndroidStudio预览支持
2.2 可组合函数 @Composable
使用该注解的函数可被用于组合成界面(可看作是一个Layout布局,即界面的某部分),默认内部元素的排列为堆叠。复用率高的建议写在顶层函数。
- 函数名首字母需要大写:为了辨识度。
- 只能由其它可组合函数调用。
- 可以接收参数:将数据转换为界面。
- 没有返回值:用来描述屏幕状态,而不是具体的组件???
- 无法修改属性或全局变量,只用来做界面描述???
- 非顺序执行:Compose会识别哪些元素优先级更高,从而优先绘制。
- 并行执行:会通过并行运行Composable函数来优化重组,因此调用某个Composable函数时可能不在同一线程中。
@Composable
fun Show(str: String) {
Text(text = "Hello ${str}!")
}
2.3 预览效果 @Preview
使用该注解的可组合函数可以在AndroidStudio右上角直接预览效果,而不用真机或模拟器。AS按出prev能快速打出模板代码。
- 只能修饰无参可组合函数:可以用无参函数包裹有参函数传个值给它来预览。
showBackground | 预览默认是不现实背景色的,设为true才显示。 |
@Preview
@Composable
fun WrapperShow() {
Show("Word") //包裹一层再传个值
}
@Composable
fun Show(str: String) {
Text(text = "Hello ${str}!")
}
2.4 Activity调用
- 需要继承的是ComponentActivity。
- 使用 setContent { } 替换 setContentView( )。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { // 设置显示内容,用来替换setContentView
Show("Hello World!")
}
}
}