高级 Kotlin 技巧: 在 Android 开发中释放
combine
的强大力量! 🧠💪举NHL示例充分利用combine
以合并 3 个流用来增强简明性和可读性
简介
在 Android 开发领域, Kotlin 已成为一种强大而富有表现力的语言. 其突出特点之一是能够使用协程和Flow来处理异步操作. 在众多可用工具中, combine
函数为同时处理多个流提供了一种简洁高效的方法.
使用combine
是初级, 中级还是专家级方法?
虽然与基本的协程概念相比, combine
是一个相对高级的功能, 但它并不是专家的专属. 只要扎实地理解了协程和Flow, 中级开发人员就能有效地利用combine
来增强他们的 Android 应用程序.
初始代码与重构代码的对比
上图是 NHL 球队比赛的屏幕截图; 代码从三个不同的服务中并行获取数据: 今天的比赛, 选定日期的比赛和球队排名.
分解初始方法
代码不是以线性方式等待每个服务调用依次完成, 而是利用async
和await
模式为每个请求启动并发 协程, 从而提高性能.
- 每个Flow都有单独的
async
块. - 手动处理延迟结果和UI状态.
- 缺乏明确的
try-catch
块, 无法从容应对失败. - 使用
firstOrNull
, 只能得到第一个结果. 如果有新数据(玩家信息的实时更新, 时间变化等)怎么办?
fun loadScreenData(isRefreshedGames; Boolean, date: String) {
viewModelScope.launch {
val todayOnlyGamesDeferred = async {
repository.getGames(localDate.format(date)).firstOrNull()?.games.orEmpty()
}
val anyDayGamesDeferred = async {
repository.getGames(_selectedDate.value).firstOrNull()?.games.orEmpty()
}
val teamsDeferred = async {
repository.getStandingsNow().firstOrNull().orEmpty()
}
_uiState.emit(
GamesUiState.Success(
games = if (isRefreshedGames) anyDayGamesDeferred.await() else todayOnlyGamesDeferred.await(),
teams = teamsDeferred.await()
)
)
}
}
使用
combine
的重构方法- 使用单个
combine
调用来组合Flow, 该调用依赖于非阻塞 D.I. ioDispatcher. - 使用 lambda 函数将合并的值转换为所需的UI状态.
- 使用
collect
直接发送UI状态. - 由
try-catch
块包围, 用于处理调用失败或任何类型的异常. ❌⛔❗✅
suspend fun loadScreenData(isRefreshedGames; Boolean, date: String) = withContext(ioDispatcher) {
try {
viewModelScope.launch(coroutineExceptionHandler) {
val todayOnlyGamesFlow = repository.getGames(localDate.format(date)).map { it.games }
val anyDayGamesFlow = repository.getGames(_selectedDate.value).map { it.games }
val teamsFlow = repository.getStandingsNow().map { it }
combine(todayOnlyGamesFlow, anyDayGamesFlow, teamsFlow) { todayGames, anyDayGames, teams ->
GamesUiState.Success(
games = if (withRefreshedGames) anyDayGames else todayGames,
teams = teams
)
}.collect { uiState ->
_uiState.emit(uiState)
}
}
} catch (e: Throwable) {
_uiState.emit(GamesUiState.Error(e))
}
}
摘要: 为什么在 Android 中使用
combine
?- 简化代码:
combine
提供了一种简洁, 可读的方式来处理多个Flow, 使你的代码更易于理解和维护. - 高效数据处理: 通过组合Flow, 你可以同时处理多个来源的数据, 从而提高性能.
- 主动更新:
combine
允许对UI状态进行主动更新, 确保其始终反映最新数据. - 增强灵活性:
combine
可灵活处理组合值, 允许你在输出最终结果之前执行额外的变换或计算.
今天要分享的内容就这么些啦!
一家之言, 欢迎斧正!
Happy Coding! Stay GOLDEN!