学习 Compose 系列(一)环境配置、概念理解、初体验

学习 Compose 系列(一)环境配置、概念理解、初体验

Jetpack Compose 是用于构建原生界面的新款 Android 工具包。它可简化并加快 Android 上的界面开发。使用更少的代码、强大的工具和直观的 Kotlin API,快速让应用生动而精彩。

image.png

Compose 作为一条新的构建界面的工具,不同于原来解析 xml 生成,应用开发方式也与原来不同,需要重新理解其原理。Compose 放在 Jetpack 中,和 ViewModel LiveData 结合,目标是开发更高效,应用更健壮。官网地址

之前通过 kotlin + xml 编写UI界面,两种语言无法互通,xml 本身很不灵活,使得UI编写很麻烦,无法大量复用;Compose 提供的工具使得只使用 kotlin 一种语言编写 UI 和动画,加上IDE的预览,使得我们可以更快速的完成界面的 UI,而且灵活性和复用性大大提升。定义好 UI 界面,关联上相关的状态值,然后逻辑层只控制状态值的变更,状态变更自动同步到UI变化。

1. 下载预览版本 Android Studio

目前 compose 为 beta 版本,需要下载预览版 as 才能体验。下载地址

image.png

2. 创建支持 Compose 的应用

image.png

3. 代码结构变化

image.png

基类变更为:ComponentActivity,之前使用的 AppCompatActivity 变更为 FragmentActivity 和 ComponentActivity 的子类;可以看到如果要使用 fragment 应该还是需要改基类为 AppCompatActivity。

image.png

image.png

ComponentActivity 的扩展函数 setContent,找到或者构建ComposeView。最后调用 Activity.setContentView(view,layoutParams) 设置界面内容。最终 View 界面的相关概念没有变化,只不过将一个 ComposeView 设置到 Activity 中。

image.png

ComposeView 继承 AbstractComposeView,父类时一个 ViewGroup,内部有一个 Composition 和 CompositionContext。 在 attachToWIndow 时调用到扩展函数 ViewGroup.SetContent

image.png

image.png

1
2
3
4
5
6
7
8
9
10
11
12

override fun onAttachedToWindow() {
super.onAttachedToWindow()

if (composition != null) {
checkViewTreeOwners()
}

if (shouldCreateCompositionOnAttachedToWindow) {
ensureCompositionCreated()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private fun ensureCompositionCreated() {
if (composition == null) {
if (isAttachedToWindow) {
checkViewTreeOwners()
}
try {
creatingComposition = true
composition = setContent(
parentContext ?: findViewTreeCompositionContext() ?: windowRecomposer
) {
Content()
}
} finally {
creatingComposition = false
}
}
}

生成一个 AndroidComposeView (继承ViewGroup)添加到界面中, doSetContent 将传入的 @Composable 函数赋值。真正将函数转换成具体的界面是在 AndroidComposeView 中进行转换的

1
2
3
4
5
6
7
8
9
10
11
12
13
internal fun ViewGroup.setContent(
parent: CompositionContext,
content: @Composable () -> Unit
): Composition {
GlobalSnapshotManager.ensureStarted()
val composeView =
if (childCount > 0) {
getChildAt(0) as? AndroidComposeView
} else {
removeAllViews(); null
} ?: AndroidComposeView(context).also { addView(it.view, DefaultLayoutParams) }
return doSetContent(composeView, parent, content)
}

构造函数、onMeasure、onLayout、dispatchDraw。基本上就是Compose 框架的转换逻辑。

image.png

image.png

image.png

image.png

4. 运行体验

content 区域生成了一个 AndroidComposeView。

image.png

image.png

总结

Compose 工具包的出现使得声明式UI在开发效率和代码复用性上大大提升。性能上可以看到变化主要时在声明UI转换为真正的View的过程,以及通知 view 状态变更;具体的性能细节问题后续系列探索。

下篇:学习 Compose 系列(二)UI之主题、布局、交互


欢迎和我一起交流学习

文章来自: http://hanks-zyh.github.io/