Jetpack Compose 是 Google 用于 Android 应用程序开发的全新现代声明式 UI 框架。Compose 结合了从以前的 UI 工具包中获得的十多年的经验和 Kotlin 编程语言的强大功能,为 Android 开发人员提供了既强大又令人耳目一新的 UI 开发体验。
Jetpack Compose如何构建更快的Android应用程序?本文将通过以下方式快速启动你对 Jetpack Compose 的学习:
- 快速演示 Compose UI 应用程序的构建块
- 介绍一些编写更灵活和可扩展的可组合代码的指南
- 详细说明在使用 Compose 时提高开发人员生产力的几个技巧
什么是 Jetpack Compose?
Jetpack Compose构建Android应用教程:Jetpack Compose 与传统的 Android 视图系统最明显的区别是 Compose UI 完全是用 Kotlin 编写的。不再需要将 XML 用于布局、样式、排版、颜色或其他 UI 相关元素。
@Composable
fun Composable() {
Text("Hello World!")
}
你熟悉的视图、TextViews
、按钮LinearLayouts
等已经一去不复返了。Compose 应用程序是使用 Composable 函数而不是视图函数构建的。可组合函数用@Composable
单独的 UI 元素进行注释并表示。我们可以使用预定义的 Composables 或定义我们自己的。
Jetpack Compose 利用来自其他声明式框架(例如 React 和 Flutter)的模式,为习惯于声明式编程的人提供直观和熟悉的体验。因为 Compose 应用程序是用 Kotlin 编写的,所以很容易使用你习惯使用的所有相同的控制流结构和语言功能来描述你的 UI。
@Composable
fun Title(message: String?) {
if(message == null) {
Text("error")
} else {
Text(message)
}
}
Compose 承诺简化和加速 UI 开发,并具有成为 Kotlin 未来 Android 开发的巨大潜力。那么,你如何开始构建 Jetpack Compose 应用程序呢?
使用 Jetpack Compose
如何使用Jetpack Compose构建安卓程序?要开始使用 Jetpack Compose,你需要做几件事来设置你的项目。
- 下载最新的稳定版 Android Studio
- 使用 Android Studio 创建一个新的 Android 项目
- 将你应用的 minSdk 版本设置为 21 (Android 5.0) 或更高版本
- 将以下 Compose 依赖项添加到你的
build.gradle
文件中
// build.gradle.kts
implementation("androidx.compose.ui:ui:1.0.1")
implementation("androidx.compose.ui:ui-tooling:1.0.1")
implementation("androidx.compose.foundation:foundation:1.0.1")
implementation("androidx.compose.material:material:1.0.1")
创建项目并添加这些依赖项后,你应该能够同步项目并开始使用 Compose API。首先,让我们在创建的 default 中显示“Hello World”消息Activity
。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello world!")
}
}
}
请注意,没有调用setContentView()
. 我们可以定义一个基于 Compose 的 UI 来Activity
使用该setContent{}
函数,而不是膨胀基于 XML 的布局。在传递给 的 lambda 中setContent()
,我们可以添加 Composables 来定义我们的用户界面。
让我们来看看开始使用 Jetpack Compose 构建交互式应用程序所需的一些最常见的构建块
掌握可组合的基础知识
添加文字
需要向你的应用程序添加一些文本吗?你可能想要使用Text
Composable。
setContent {
Text(text = "Hello World")
}
该Text
可组合是科特林功能,其中包含很多可选参数,使你可以配置你的文字应该是什么样子的。
setContent {
Text(
text = "Hello World",
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Button Composable
要在你的 UI 中显示一个简单的按钮,你可以使用Button
Composable。
Button(onClick = {}) {
Text("Button Text")
}
Button
是 Compose 如何支持组合而不是严格继承的一个很好的例子。请注意,我们将 lambda 传递给Button
函数。该 lambda 定义了 的内容Button
。在这种情况下,我们按钮的内容是一个简单的文本元素。
这是 Compose 中的常见模式。Composables 通常会使用尾随的 lambda 来定义它们的内容,从而使它们更灵活且更易于使用。
Column
和Row
组合物
Jetpack Compose如何构建更快的Android应用程序?为了帮助对齐诸如Text
或 之类的元素Button
,我们需要容器来帮助我们排列这些元素。你可能会遇到的前两个此类容器是Column
和Row
。
Column
将子元素垂直放置,一个接一个。
Column(
modifier = Modifier.fillMaxSize(1f),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Hello World",
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Button(onClick = {}) {
Text("Button Text")
}
}
如果你需要横向内容,可以使用Row
代替Column
。
Row(
modifier = Modifier.fillMaxSize(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
text = "Hello World",
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Button(onClick = {}) {
Text("Button Text")
}
}
LazyColumn
而LazyRow
对于大型数据集
如何使用Jetpack Compose构建安卓程序?处理大量数据并需要高性能容器?而不是使用Column
and Row
,我们可以使用LazyColumn
, and LazyRow
,它们提供更有效的资源回收和更快的绘图性能。这两个 Composable 在概念上与RecyclerView
.
要创建LazyColumn
,我们可以更改Column
为LazyColumn
,然后在item{}
可组合中定义每个 UI 元素,它定义列表中的各个项目,因此我们可以定义不同的项目类型而无需适配器。
LazyColumn(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(1f),
) {
item { Text("1") }
item { Text("2") }
item { Text("3") }
item { Text("4") }
item { Text("5") }
item { Text("6") }
item { Text("7") }
item { Text("8") }
item { Text("9") }
item { Text("10") }
}
需要根据静态计数或数据集合创建一堆项目吗?我们可以使用该items()
函数在我们的LazyColumn
.
LazyColumn(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(1f),
) {
items(100) { index ->
Text("$index")
}
}
a LazyColumn
or内的项目LazyRow
不必相同。你可以随意混合 UI 元素 — 无需单独的适配器或布局。这突出了 Jetpack Compose 相对于现有 UI 系统的强大功能和灵活性。
在 Compose 中处理填充和边距
Jetpack Compose如何构建更快的Android应用程序?我们如何在 Compose 中使用填充和边距?好吧,Compose 通过提供一个概念来简化它——填充。
我们可以通过应用定义任何元素的填充Modifier
。修饰符允许我们配置一个 Composable 来控制大小、填充、焦点状态、点击处理程序等。
要将填充添加到上一个示例中的项目列表,我们可以按如下方式更新我们的代码:
LazyColumn(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(1f),
) {
items(100) { index ->
Text(
text = "$index",
modifier = Modifier.padding(16.dp)
)
}
}
这里发生了一些有趣的事情。首先,命名参数的使用在 Compose 代码中很常见。其次,我们可以通过Modifier
直接引用并在其上调用方法来开始构建修饰符。
要添加填充,我们可以调用padding()
并传入一个维度值。在这里,我们使用一个名为的扩展属性dp
来方便地将原始值16
转换为维度值。
更好的 Composables 的技巧
我们现在已经介绍了最常见的 Composables,以及一些常见的使用模式。随着 Android 社区继续使用 Compose、新模式和约定,最佳实践将会出现。
当你使用 Jetpack Compose 时,这里有一些技巧可以帮助你编写更灵活、可扩展的 Compose 应用程序。
Jetpack Compose构建Android应用教程:利用默认参数值和命名参数
与 Java 相比,使用 Kotlin for Compose 的一大优势是我们可以利用 Kotlin 语言功能,例如命名参数和默认参数值。
命名参数允许我们在调用函数时混合参数的顺序。这使得我们的 Composable 函数更易于使用,并有助于使代码非常易读。
默认参数允许我们编写一个可以以多种不同方式使用的可组合。不必定义许多重载函数,我们可以使用一个定义合理默认值的函数。
观察Text
我们一直在使用的函数:
@Composable
fun Text(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) { ... }
此函数提供了多种方法来控制绘制文本时的外观。但是,因为唯一需要的参数是 ,所以text
这个 Composable 的基本用法可以避免全套参数的复杂性。
小型和私人功能
当你构建屏幕和可组合物时,请尽量使你的个人可组合物小而集中。将 UI 的各个部分重构为更小的函数以限制它们的范围,并使你的代码更易于阅读和遵循。
你还可以利用可见性修饰符来帮助保持你的代码井井有条。想象一下,你正在为特定屏幕构建 UI,并将所有可组合项放在一个文件中。
如果该文件只公开一个公共或内部可组合,那么你可以在该文件中使用任意数量的小型、集中、私有的可组合,而不会污染项目的全局命名空间。
基于插槽的设计
如何使用Jetpack Compose构建安卓程序?在构建自定义可组合物时,通过核心和材料库从可组合物提供程序中获取灵感。这些函数利用基于插槽的方法进行 API 设计。
许多 Compose API 不是严格执行必须如何组合或使用事物,而是允许调用者自定义应如何绘制内容,以便可以根据特定提要对其进行自定义。
例如,让我们重温之前的按钮示例。
Button(onClick = {}) {
Text("Button Text")
}
Button
不使用字符串来显示文本。它让调用者决定文本的显示方式。或者也许我们根本不希望按钮中出现文本。使用这种基于槽的方法,我们可以为按钮使用图标,或者图标、文本等的复杂布局。
在创建可在你的应用程序中重用的低级可组合物时,这种方法会带来好处。一个很好的例子是“基本卡”。
@Composable
fun BaseCard(content: @Composable ColumnScope.() -> Unit) {
Card(elevation = 4.dp) {
Column(content = content)
}
}
你可以定义根卡片的外观,但将内容留给调用者传递。这种模式对于为你的团队构建一组可重用的组件非常有用。
提高生产力和开发人员体验的技巧
Jetpack Compose 的主要目标之一是让 Android 开发更快、更有趣。考虑到这一点,有一些有用的事情需要注意。
可组合预览
Jetpack Compose如何构建更快的Android应用程序?Jetpack Compose 支持预览,这使我们无需部署到设备即可预览我们的 Composable 的外观。小的更改,例如更新填充常量,可以立即更新预览,无需任何类型的刷新或重建。
要定义预览,我们可以编写一个新的 Composable 并添加@Preview
注释。
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
MyApplicationTheme {
Greeting("Android")
}
}
当我们构建应用程序时,这些预览就可以直接在 Android Studio 中看到。
预览也可以通过多种有趣的方式进行定制。
例如,可以将预览配置为显示默认背景、更改预览设备大小或更改深色主题:
@Preview(showBackground = true, device = Devices.PIXEL_4)
@Composable
fun Pixel4Preview() {
MyApplicationTheme {
Column(
modifier = Modifier.fillMaxSize(1f),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Greeting("Android")
}
}
}
我们甚至可以在同一个文件中定义多个预览,以并排查看这些预览,并查看我们的 Composable 在各种配置中的外观的多个示例。
通过利用这些预览,我们可以实现更快的迭代周期,因为我们可以轻松地可视化 UI 的更改,而无需部署我们的应用程序。
使用 Jetpack Compose 缩短构建时间
Composable 预览的一个潜在问题是,它们确实需要对你的应用程序进行一些重建以进行较大的代码更改。对于构建时间较慢的应用程序,这会使预览的用处大大降低。
为了帮助解决这个问题,你可以做两件事。
第一个是通过添加org.gradle.caching=true
到gradle.properties
文件来启用本地 Gradle 构建缓存。启用本地构建缓存后,每次刷新预览时,你的构建将不得不重建更少的代码,这应该会导致更快的预览。
除了启用本地 Gradle 构建缓存外,你还可以考虑模块化你的应用程序。如果你可以将 Composable 预览隔离到具有较少依赖项的较小模块,则可以减少刷新预览时必须重新编译的代码量。
Jetpack Compose构建Android应用教程总结
在这篇文章中,我们只触及了 Jetpack Compose 的皮毛。希望这有助于阐明 Compose 与我们过去 10 年构建 Android 应用程序的方式有何不同,并可能让你对未来 10 年的样子感到兴奋。