大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
没有伞的孩子必须努力奔跑!你不勇敢,没人替你坚强。只有经历过地狱般的折磨,才有征服天堂的力量。只有流过血的手指才能弹出世间的绝唱。
简介
Compose 是用于构建原生 Android 界面的新工具包。是Android全新的UI框架,它使用更少的代码、强大的工具和直观的 Kotlin API,可以帮助简化并加快 Android 界面开发。
为什么要学习Compose
基本要求
创建Jetpack Compose 工程步骤
现有项目添加支持Compose
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
buildFeatures {
compose true //支持compose
}
composeOptions {
kotlinCompilerExtensionVersion compose_version //设置kotlin编译器版本
}
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
第一个Compose程序
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
//主题
ComposeProjectTheme {
// 一个带有背景颜色的容器可理解为R.layout.xxx
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
//可组合函数
Greeting("Android")
}
}
}
}
}
//可组合函数
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true, showSystemUi = true, device = Devices.AUTOMOTIVE_1024p)
@Composable
fun DefaultPreview() {
ComposeProjectTheme {
Greeting("Android")
}
}
页面预览
@Preview(showBackground = true, showSystemUi = true, device = Devices.AUTOMOTIVE_1024p)
@Composable
fun DefaultPreview() {
ComposeProjectTheme {
Greeting("Android")
}
}
@Preview注解用来构建预览页面。参数包括,背景,是否显示系统UI,模拟设备等等。
编程思想
声明式编程
长期以来,Android视图层次结构一直可以表示为界面控件树,由于应用程序的状态会因用户交互等因素而发生变化,因此界面层次结构需要更新以显示当前的数据,最常见的更新方式就是通过findViewById 等函数遍历view树,找到对应的view,然后调用view的相应的方法进行更新。而Compose是根据数据变化而自动更新UI层次结构。
可组合函数
@Composable
fun Greeting(isLogin:Boolean = false) {
val content = if (isLogin) "登录成功" else "请登录"
Text(text = "Hello $content!")
}
可组函数不仅可以写展示页面也可以写逻辑代码
重组
在Android View中,如果想要修改某个控件,需要调用控件的方法,而在Compose中,可以使用新的数据再次调用可组合函数进行修改,这就导致函数进行重组,重组就是系统根据需要使用新数据重新绘制的函数来重组组合,Compos可以智能的仅重组已更改的控件。
@Composable
fun Greeting(isLogin:Boolean = false) {
val content = if (isLogin) "登录成功" else "请登录"
Text(text = "Hello $content!")
}
当Compose根据新数据进行重组时,它仅调用可能已更改的函数或者lambda,跳过其余函数或lambda,通过跳过所有未更改的参数的函数或lambda,Compose就可以重组了。
可组合函数如果被频繁进行调用,如动画,为了避免动画执行过程中的卡顿,尽量使用后台协程中执行,并将值结果作为参数传递给可组合函数。
Compose跟原生的View到底是什么关系?是跟Flutter一样完全基于Skia引擎渲染,还是说和原生View一样?
override fun onResume() {
super.onResume()
//测量布局
window.decorView.postDelayed({
( window.decorView as? ViewGroup)?.let {
printViewCount(it,1)
}
},300)
}
fun printViewCount(view: View,index:Int){
Log.e(TAG, "布局 第: $index 层 --$view")
if (view is ViewGroup){
view.children.forEach {
printViewCount(it,index+1)
}
}
}
我们通过日志打印,在页面展示出来后,第三秒还是遍历当前页面的整个布局层次,来看一下布局层次是否和我们代码添加的一致.
通过日志分析可以看出来,布局的最后一层是AndroidComposeView,没有我们代码添加的布局,那么我们添加的布局在哪?
我们先看布局结构层次
public fun ComponentActivity.setContent(
parent: CompositionContext? = null,
content: @Composable () -> Unit
) {
val existingComposeView = window.decorView
.findViewById<ViewGroup>(android.R.id.content)
.getChildAt(0) as? ComposeView
if (existingComposeView != null) with(existingComposeView) {
setParentCompositionContext(parent)
setContent(content)
} else ComposeView(this).apply {
// Set content and parent **before** setContentView
// to have ComposeView create the composition on attach
setParentCompositionContext(parent)
setContent(content)
// Set the view tree owners before setting the content view so that the inflation process
// and attach listeners will see them already present
setOwners()
setContentView(this, DefaultActivityContentLayoutParams)
}
}
性能提升
喜欢Compose的同学,请关注或收藏一下本篇文章,后续跟随小编一起学习Compose。有精通Compose的同学欢迎评论区留言!