我从 Android Developers Codelab 找到了一个代码示例,它涉及 Jetpack Compose 中的导航,它是“Rally Material Study”,代码位于 GitHub 上:NavigationCodeLab
尽管我最初想专注于导航,但我很难理解一些函数调用和 lambda。
在“OverviewScreen”可组合项中,“AccountsCard”被称为:
//other composable code
AccountsCard(
onClickSeeAll = onClickSeeAllAccounts,
onAccountClick = onAccountClick
)
//other composable code
AccountsCard
定义如下:
private fun AccountsCard(onClickSeeAll: () -> Unit, onAccountClick: (String) -> Unit) {
val amount = UserData.accounts.map { account -> account.balance }.sum()
OverviewScreenCard(
title = stringResource(R.string.accounts),
amount = amount,
onClickSeeAll = onClickSeeAll,
data = UserData.accounts,
colors = { it.color },
values = { it.balance }
) { account ->
AccountRow(
modifier = Modifier.clickable { onAccountClick(account.name) },
name = account.name,
number = account.number,
amount = account.balance,
color = account.color
)
}
}
注意
colors = {it.color}
和values = {it.balance}
- 这基本上是我正在努力解决的问题。
UserData 使用“假用户数据”定义了一些对象,其中使用
Account
类:
@Immutable
data class Account(
val name: String,
val number: Int,
val balance: Float,
val color: Color
)
UserData.accounts
是一个带有虚假数据的List<Account>
。
AccountRow
定义如下:
@Composable
fun AccountRow(
modifier: Modifier = Modifier,
name: String,
number: Int,
amount: Float,
color: Color
) {
BaseRow(
modifier = modifier,
color = color,
title = name,
subtitle = stringResource(R.string.account_redacted) + AccountDecimalFormat.format(number),
amount = amount,
negative = false
)
}
OverviewScreenCard
:
@Composable
private fun <T> OverviewScreenCard(
title: String,
amount: Float,
onClickSeeAll: () -> Unit,
values: (T) -> Float,
colors: (T) -> Color,
data: List<T>,
row: @Composable (T) -> Unit
) {
Card {
Column {
Column(Modifier.padding(RallyDefaultPadding)) {
Text(text = title, style = MaterialTheme.typography.subtitle2)
val amountText = "$" + formatAmount(
amount
)
Text(text = amountText, style = MaterialTheme.typography.h2)
}
OverViewDivider(data, values, colors)
Column(Modifier.padding(start = 16.dp, top = 4.dp, end = 8.dp)) {
data.take(SHOWN_ITEMS).forEach { row(it) }
SeeAllButton(
modifier = Modifier.clearAndSetSemantics {
contentDescription = "All $title"
},
onClick = onClickSeeAll,
)
}
}
}
}
BaseRow
相当长,我现在跳过它,因为它本质上“只是”定义可组合项的实际外观,我也省略了OverViewDivider
,因为我认为它无助于澄清。
我的理解是从
OverviewScreen
开始调用 AccountsCard
。 AccountsCard
本身调用 OverviewScreenCard
并提供所需的参数,其中包括作为列表的 UserData.accounts,其中 OverviewScreeCard
然后获取 SHOWN_ITEMS (= 3) 项并迭代它们,每个项都调用可组合项传入 row
,而 AccountsCard
又作为 AccountRow
传递。这就是我迷失方向的地方。
我对 lambda 做了一些工作,但仍有很多东西需要理解,我想这里就是这种情况。所以我假设对
account ->
的调用中的 AccountRow
是来自 it
的 .forEach
。 it
,前三个帐户中的每一个都作为参数传递给 AccountRow 并用于构建该行。
it
和colors = {it.color}
中的values = {it.balance}
从哪里来?
和it
中的colors = {it.color}
从哪里来?values = {it.balance}
OverviewScreenCard()
将这些参数定义为带有参数的函数类型:
values: (T) -> Float,
colors: (T) -> Color,
无论您为
values
和 colors
提供什么 lambda 表达式或其他函数类型,都可以使用 it
来引用该参数。或者,如果您愿意,您可以给它一个名称:
colors = { account -> account.color },
values = { account -> account.balance }
泛型
T
将由 Kotlin 编译器推断,主要是通过传递到 row
槽参数的类型来推断。在使用 OverviewScreenCard()
时,您传入的是 Account
,只要传入参数是 colors
时 values
和 Account
能够编译,Kotlin 编译器就会满意。
我还省略了 OverViewDivider,因为我认为它无助于澄清
它正在消耗
values
和colors
。因此,“传递给这些 lambda 的实际参数值来自哪里”的问题由 OverViewDivider()
实现来回答,这不是您问题的一部分。