1. 开始之前
在本路径中,您学习了泛型、不同类型的类、集合和高阶函数。为了练习您所学到的知识,您将帮助您的团队改进他们新的事件跟踪应用。每个步骤中的说明都会描述应用的当前状态以及您需要完成的任务。
建议您使用 Kotlin Playground 来解决这些练习。
前提条件
- 完成 Android Basics with Compose 课程的 第 3 单元第 1 路径 及之前的路径。
- 熟悉 Kotlin 编程语言的基础知识,包括类、对象、集合和高阶函数。
您需要准备的
- 一台可以上网的计算机
- 能够访问 Kotlin Playground
2. 应用概述
您是事件跟踪应用团队的最新软件工程师。此应用的目的是允许用户跟踪其事件。您的团队将为您分配任务,以帮助构建应用的功能。
完成每个任务后,您应该将您的解决方案与提供的解决方案进行比较。实现所需功能的方法有很多种,因此如果您的代码与提供的解决方案代码不完全匹配,请不必担心。
使用上一个任务中提供的解决方案代码作为下一个任务的起始代码,以便从一个共同的起点开始。
3. 任务 1
另一位软件工程师已经完成了应用的一些高级工作,而您的任务是实现细节。
您需要实现 Event
类。此类用于存储用户输入的事件详细信息。(提示:此类不需要定义任何方法或执行任何操作。)
对于此任务,您需要创建一个名为 Event
的数据类。
此类的实例应该能够存储
- 事件标题,类型为字符串。
- 事件描述,类型为字符串(可以为 null)。
- 事件的一天中的时段,类型为字符串。我们只需要跟踪事件是发生在上午、下午还是晚上。
- 事件持续时间,以分钟为单位,类型为整数。
在继续之前,请尝试自己编写代码。
使用您的代码,根据以下信息创建一个实例
- 标题:学习 Kotlin
- 描述:每天至少花 15 分钟学习 Kotlin。
- 一天中的时段:晚上
- 持续时间: 15
尝试打印您的对象,以验证您是否获得以下输出
Event(title=Study Kotlin, description=Commit to studying Kotlin at least 15 minutes per day., daypart=Evening, durationInMinutes=15)
完成任务或尽力尝试后,请点击下一步查看我们的代码实现。
4. 任务 1 解决方案
您的解决方案应与以下代码类似
data class Event(
val title: String,
val description: String? = null,
val daypart: String,
val durationInMinutes: Int,
)
5. 任务 2
为了让项目按计划进行,您的经理决定使用我们提供的数据类代码。
您的团队成员使用了一段时间的 Event
类后,资深队友意识到使用字符串来表示一天中的时段并不理想。
有些开发者存储了“Morning”值,有些使用了“morning”,还有些使用了“MORNING”。
这导致了许多问题。
您的任务是通过进行重构来解决此问题。重构是在不改变代码功能的情况下改进代码的过程。一些例子包括简化逻辑或将重复的代码移至单独的函数中。
可以使用哪种类型的类来建模一组有限的离散值,以帮助解决此问题?
您的团队希望您将一天中时段的代码更改为使用枚举类。通过使用枚举类,您的队友将被迫选择提供的一天中时段值之一,从而防止出现此类问题。
枚举类应命名为 Daypart
。它应该包含三个值
MORNING
AFTERNOON
EVENING
您将如何创建此枚举类?
您将如何重构您的 Event
类来使用它?
在继续之前,请尝试现在编写您的解决方案代码。
点击下一步查看我们的代码实现。
6. 任务 2 解决方案
enum class Daypart {
MORNING,
AFTERNOON,
EVENING,
}
重构后的 Event
数据类现在使用枚举类
data class Event(
val title: String,
val description: String? = null,
val daypart: Daypart,
val durationInMinutes: Int,
)
7. 任务 3
您的同事很高兴使用重构后的 Daypart
,但他们还有其他问题。
以下代码是他们当前创建和存储用户事件的方式。
val event1 = Event(title = "Wake up", description = "Time to get up", daypart = Daypart.MORNING, durationInMinutes = 0)
val event2 = Event(title = "Eat breakfast", daypart = Daypart.MORNING, durationInMinutes = 15)
val event3 = Event(title = "Learn about Kotlin", daypart = Daypart.AFTERNOON, durationInMinutes = 30)
val event4 = Event(title = "Practice Compose", daypart = Daypart.AFTERNOON, durationInMinutes = 60)
val event5 = Event(title = "Watch latest DevBytes video", daypart = Daypart.AFTERNOON, durationInMinutes = 10)
val event6 = Event(title = "Check out latest Android Jetpack library", daypart = Daypart.EVENING, durationInMinutes = 45)
他们创建了许多事件,并且每个事件当前都需要一个单独的变量。随着创建的事件越来越多,跟踪所有事件变得越来越困难。使用这种方法,确定用户安排了多少个事件会有多困难?
您能想到一种更好的方法来组织这些事件的存储吗?
您可以用什么方式将所有事件存储在一个变量中?(注意:它必须是灵活的,因为可能会添加更多事件。它还需要高效地返回存储在该变量中的事件数量。)
您会使用哪种类或数据类型?有一种方法可以添加更多事件是什么?
现在轮到您来实现此功能了。在点击下一步查看我们的解决方案之前,请尝试编写代码。
8. 任务 3 解决方案
val events = mutableListOf<Event>(event1, event2, event3, event4, event5, event6)
9. 任务 4
您的经理很满意应用的进展,但决定用户应该能够根据事件持续时间查看其短时事件的摘要。例如,“您有 5 个短时事件。”
“短时”事件是指持续时间少于 60 分钟的事件。
使用上一个任务解决方案中的 events
变量代码,您将如何实现此结果?
点击下一步继续查看我们的解决方案。
10. 任务 4 解决方案
有多种方法可以完成此任务,以下是我们确定的方法
val shortEvents = events.filter { it.durationInMinutes < 60 }
println("You have ${shortEvents.size} short events.")
11. 任务 5
您的队友很满意应用的进展,但他们希望用户能够查看所有事件及其一天中时段的摘要。
输出应类似于
Morning: 3 events Afternoon: 4 events Evening: 2 events
使用上一步中的 events
变量代码,您如何实现此结果?
点击下一步查看解决方案代码。
12. 任务 5 解决方案
以下是我们的解决方案,但也接受其他变体。
val groupedEvents = events.groupBy { it.daypart }
groupedEvents.forEach { (daypart, events) ->
println("$daypart: ${events.size} events")
}
13. 任务 6
目前,您的同事通过使用索引找到并打印最后一个项目。使用的代码是:println("Last event of the day: ${events[events.size - 1].title}")
。
您的经理建议查阅Kotlin 文档,寻找可以简化此代码的函数。
您找到了什么函数?
尝试使用它来确认您打印出相同的结果。
点击下一步查看解决方案。
14. 任务 6 解决方案
println("Last event of the day: ${events.last().title}")
15. 任务 7
15. 任务 7
val durationOfEvent = if (events[0].durationInMinutes < 60) {
"short"
} else {
"long"
}
println("Duration of first event of the day: $durationOfEvent")
您的团队喜欢您设计的数据类,但发现每次需要将事件持续时间作为字符串时都编写代码很重复
虽然您可以通过直接向类添加方法来解决这种重复问题,但这并不理想,因为其他团队已经在他们的应用中开始使用您的事件类。如果类发生变化,他们将需要重新测试所有代码,以确保您的更改不会破坏任何内容。
在不直接更改数据类的情况下,您如何编写一个扩展属性,使其返回与上述代码相同的值?
println("Duration of first event of the day: ${events[0].durationOfEvent}")
正确实现后,您将能够使用以下代码,它将打印出与本任务开始时显示的代码相同的消息。
点击下一步继续查看解决方案。
val Event.durationOfEvent: String
get() = if (this.durationInMinutes < 60) {
"short"
} else {
"long"
}
16. 任务 7 解决方案
17. 额外练习