我如何学习使用 Jetpack Compose 开发 Android 应用程序
Jetpack Compose 和 Android 开发简介
2021 年 7 月,Google 发布了用于为 Android 应用构建原生 UI 的全新工具包 1.0 版。Jetpack Compose 是 Android 开发人员的游戏规则改变者,因为它从通过 XML 设计的 UI 转变为完全动态的声明式编程。
声明式编程是一种编程方法,开发人员定义所需的输出或结果,而不是指定实现它所需的步骤。在 Android Jetpack Compose 的上下文中,声明式编程意味着开发人员描述 UI 元素及其行为,而框架会根据需要自动负责渲染和更新它们。
这种编写代码的方法非常方便,因为与 XML 相比,它留下的错误余地更小。
在 2023 年,作为 Android 开发人员,Jetpack Compose 是您应该添加到工具包中的必备工具,因为越来越多的公司正在对其进行调整。
如何开始学习 Jetpack Compose(路线图)
当我在 2023 年初决定学习 Android 开发时,我对 Android 没有任何经验。这使得学习的前几个步骤变得困难,因为我遇到了很多让我不知所措的术语。
仅举几例,一些让我不知所措的术语是:
- MVVM(模型视图视图模型)
- 状态
- 状态提升
- 数据存储
- Hilt(依赖注入)
- 房间(SQLite)
1. 如何使用 Jetpack Compose 管理 Android 中的活动
在 Jetpack Compose 中,推荐的架构模式是单 Activity 模式,在这种模式下,您有一个Activity来托管您应用程序的所有屏幕。不是使用多个Activity类,而是将每个屏幕实现为一个可组合的函数,屏幕之间的导航由 Jetpack Navigation 组件管理。
以下是如何在 Jetpack Compose 中实现单活动模式的示例:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(navController, startDestination = "screen1" ) {
composable("screen1") { screen1(navController) }
composable("screen2") { screen2(navController) }
composable("screen3") { screen3(navController) }
}
}
}
}
2.可组合函数
在 Jetpack Compose 中,函数是设计声明式 UI 的构建块。
每个 Composable 函数都以 @Composable 注释开头。并且可组合函数只能从其他可组合函数的上下文中调用。
在 Jetpack Compose 中,您可以调用一组不同的预定义可组合函数来设计您的 UI 元素。您还可以像上面的示例一样创建可组合函数。开始使用可组合函数的最佳资源是Android Basics With Compose课程。本课程是熟悉 Jetpack Compose 和 Kotlin 的非常简单易懂的起点。
@Composable
fun ComposeUI(){
Box(ContentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
Text("This is a Composable Function)
}
}
https://developer.android.com/courses/android-basics-compose/course
在 Jetpack Compose 中,函数是设计声明式 UI 的构建块。
每个 Composable 函数都以 @Composable 注释开头。并且可组合函数只能从其他可组合函数的上下文中调用。
在 Jetpack Compose 中,您可以调用一组不同的预定义可组合函数来设计您的 UI 元素。您还可以像上面的示例一样创建可组合函数。开始使用可组合函数的最佳资源是Android Basics With Compose课程。本课程是熟悉 Jetpack Compose 和 Kotlin 的非常简单易懂的起点。
3. Jetpack Compose 中的 UI 状态
UI 状态是指用户界面的当前状态或条件。它包括 UI 元素的可见性、文本、颜色和其他属性等属性。UI 状态可以根据用户交互或程序逻辑动态更改。
在 Android Jetpack Compose 的上下文中,UI 状态管理是构建动态和交互式 UI 的重要组成部分。Jetpack Compose 提供了多种状态管理机制,例如 State 和 MutableState 来管理 UI 元素的状态。
状态是一种价值持有者,可以持有单一价值,并且可以观察到变化。当 State 值发生变化时,Compose 框架会自动触发受影响的 UI 元素的重组以反映更新后的状态。MutableState 是 State 的可变版本,允许您直接更新其值。
以下是使用 State 管理 Jetpack Compose 中按钮可见性的示例:
@Composable
fun MyScreen() {
var isButtonVisible by remember { mutableStateOf(true) }
Column {
Button(
onClick = { isButtonVisible = !isButtonVisible }
) {
Text(text = "Toggle Button")
}
if (isButtonVisible) {
Button(
onClick = { /* do Something */}
) {
Text(text = "My Button")
}
}
}
}
在此示例中,我们使用remember函数声明了一个名为isButtonVisible的可变状态变量。
remember函数用于状态管理。它允许您在重新组合 UI 时记住一个值。
在上面的代码中,每次按下 Toggle Button 时,其下方标记为“My Button”的按钮都会消失并重新出现。
4. Jetpack Compose 中的状态提升
在 Jetpack Compose 中设计应用程序时,状态提升是一种常见的设计模式。它允许您将 UI 和 UI 的 State 管理分开。这是一种常见的做法,可以减少出现错误和错误的机会。
要将状态提升应用于可组合函数,您只需将 mutableState
变量移到函数外部,并将变量和事件侦听器作为参数传递给该函数。
@Composable
fun MyScreen() {
var isButtonVisible by remember { mutableStateOf (true) }
MyButton(isButtonVisible) {
isButtonVisible = !isButtonVisible
}
}
@Composable
fun MyButton(isVisible: Boolean, onClick: () -> Unit) {
Button(
onClick = onClick,
) {
Text(text = "My Button")
}
if(isVisible) {
Text(text= "Text is Visible")
}
}
在上面的代码中,isButtonVisible mutableState 变量已从MyButton可组合函数提升到MyScreen可组合函数。这样MyButton函数就无法直接访问更改状态变量的值。
一旦你熟悉了状态提升,最终你会将一个屏幕的所有状态变量移动到一个单独的文件/类中。这将使 UI 本身仅观察状态,而不是定义状态。
5. Jetpack Compose 中的导航
一旦您熟悉了通过 Jetpack Compose 在 Android 应用程序中设计 UI 和管理状态,自然而然的一步就是弄清楚如何从一个屏幕导航到另一个屏幕。
当我开始学习 Jetpack Compose 时,Compose Navigation 是我在代码中见过的最令人头疼的概念之一。当您开始学习 Compose 导航时,您会听到 NavHost、NavController、NavGraph、NavDestinations
等术语。老实说,跟上什么是什么可能会让人感到困惑。所以我会为你分解它。
在我们开始之前,第一步是将 Jetpack Compose Navigation
依赖项添加到您的 build.gradle 应用模块。
dependencies {
def nav_version = "2.5.3"
implementation "androidx.navigation:navigation-compose:$nav_version"
}
请务必添加最新版本的导航依赖项。您可以在此处找到最新版本。
https://developer.android.com/jetpack/androidx/releases/navigation
现在,您只需要了解什么是 NavHost
和什么是 NavController
。其余的作为初学者是无关紧要的。您可以稍后自行研究这些主题,但现在,我们不要贪多嚼不烂。
NavController:NavController
是一个 Jetpack Compose 工具,使用它我们可以轻松地管理我们应用程序中不同屏幕之间的导航,而不必担心管理返回堆栈或自己实现复杂的逻辑。
我们必须将 navController
作为参数传递给负责导航到其他屏幕的每个屏幕。
NavHost :NavHost
是一个容器,其中包含您可以导航到的不同目的地。它是您应用程序内导航的起点。
@Composable
fun MyApp () {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "screen1" ) {
composable( "screen1" ) { Screen1(navController = navController) }
composable( "screen2" ) { Screen2(navController = navController) }
}
}
@Composable
fun Screen1 (navController: NavController ) {
Column {
Text( "This is Screen 1" )
Button(onClick = { navController.navigate( "screen2") }) {
Text( "Go to Screen 2" )
}
}
}
@Composable
fun Screen2 (navController: NavController ) {
Column {
Text( "This is Screen 2" )
Button(onClick = { navController.popBackStack() }) {
Text( "返回屏幕 1" )
}
}
}
要初始化 navController
,我们调用rememberNavController
函数。
val navController = rememberNavController()
在此之后,我们可以创建导航入口点,即我们的 NavHost。
NavHost(navController = navController, startDestination = "screen1") {
composable("screen1") { Screen1(navController = navController) }
composable("screen2") { Screen2(navController = navController) }
}
请注意,字符串“screen1”作为startDestination
的参数传递,这告诉 navHost
在编写 UI 时它将加载的第一个屏幕是 Screen1()
。目标字符串通过composable(“destination_string_here”)
函数绑定到 UI 屏幕(可组合函数)。
6. 使用 DataStore 持久化数据
DataStore是一个 Android 库,它提供了一种比SharedPreferences更灵活、更高效的方式来存储键值对数据。DataStore 旨在与 Kotlin 协程和 Jetpack Compose 无缝协作。它还内置了对可空类型和列表等类型的支持。
在 Jetpack Compose 中,DataStore 可用于跨不同的可组合项管理状态。通过使用 DataStore 的可观察特性,开发人员可以在数据发生变化时自动更新 UI。此外,DataStore 可用于存储用户首选项,例如用户的语言首选项、字体大小或主题。它还常用于存储少量的应用程序状态,例如用户是否看过特定的教程或介绍屏幕。
7. Jetpack Compose 中使用 Room 的数据持久化
Room是 Android Jetpack 套件中一个功能强大的库,可让您轻松地在 Android 应用程序中实现数据持久化。Room 建立在 SQLite 之上,并提供用于处理数据库的高级 API。
要开始在本地留出空间来持久化数据,您应该对数据库和 SQL 的工作原理有很好的了解。如果没有这种理解,您很可能会发现自己不知所措。我建议您只有在对上述主题有很好的理解之后才深入研究这个主题。
8. 使用 Jetpack Compose 实现模型视图 ViewModel
MVVM 或 Model View ViewModel 是一种软件架构模式,它将应用程序分为三个主要组件:模型,代表数据和业务逻辑,视图,代表用户界面,以及 ViewModel,充当中间人模型和视图。
在 MVVM 中,ViewModel 通过数据绑定机制将 Model 中的数据暴露给 View,并接收来自 View 的输入事件来更新 Model。这种关注点分离使代码更易于维护和测试,并允许更好的模块化和灵活性。
将 MVVM 与 Jetpack Compose 结合使用是天作之合,因为 Compose 被设计为声明式和反应式。ViewModel 可以保存 UI 的状态并将其公开给可组合函数,然后这些函数可以根据当前状态渲染 UI。这允许将 UI 和业务逻辑之间的关注点完全分离,并使测试和维护代码变得容易。
将 MVVM 与 Jetpack Compose 结合使用的一些好处包括:
关注点分离: MVVM 有助于分离 UI 和业务逻辑,使代码更易于理解和维护。
可测试性: MVVM 使得为业务逻辑和 ViewModel 编写单元测试变得更加容易,因为它们可以独立于 UI 进行测试。
灵活性: MVVM 允许在如何呈现和操作数据方面具有更大的灵活性,因为 ViewModel 可以以不同的方式转换数据并将其公开给 UI。
可重用性: MVVM 促进了模块化和可重用性,使得跨多个屏幕或组件使用相同的业务逻辑和数据变得更加容易。
总而言之,将 MVVM 与 Jetpack Compose 结合使用是一种最佳实践,可以带来更清晰、更易于维护的代码和更好的整体用户体验。
9. Jetpack Compose 中使用 Hilt 的依赖注入
Hilt是一个用于 Android 应用开发的依赖注入 (DI) 库,它是 Android Jetpack 库套件的一部分。它建立在 Dagger 之上,并为您的 Android 应用程序中的 DI 提供了一个更简单、更精简的 API。
Hilt 旨在简化应用程序组件(例如 Activity、Fragments 和 ViewModel)的管理和提供依赖项。它通过使用注释来声明依赖关系并在编译时生成必要的代码来实现这一点。
依赖注入可以简化您的开发/调试过程。它可以帮助您避免编写有缺陷的代码,并为您完成很多繁重的工作。这是一个稍微高级的概念,尽管不是太难,所以我建议您在学习完其他所有内容后开始学习它。
https://developer.android.com/training/dependency-injection/hilt-android
结论
总而言之,Jetpack Compose 是一个非常强大且有用的库,可用于为 Android 编写声明式 UI。它有它的怪癖,并且不时有更新
Android 有很多独特的概念,我们必须了解这些概念才能开发出好的 Android 应用程序。我只介绍了一些可以帮助您迈出第一步的基本概念。在介绍了这些主题之后,您应该留意可以添加到工具包中以成为更好的开发人员的工具。