在 Jetpack Compose 中更新 AndroidView 状态
Updating AndroidView state in Jetpack Compose
今天早上遇到了 AndroidView 的奇怪情况。
我有一个如下所示的 ProductCard 界面
interface ProductCard {
val view: View
fun setup(
productState: ProductState,
interactionListener: ProductCardView.InteractionListener
)
}
该接口可以由多个视图实现。
呈现 AndroidView
列表的可组合项使用 ProductCard
获取视图并在发生重组时传入状态更新。
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
provider.setup(product, interactionListener)
}
}
}
}
对于此示例,与 ProductCard 视图的任何交互(调用 ProductCard.setup()
)都不会更新屏幕。日志记录显示状态已更新,但要注意的是每个按钮仅更新一次。例如,我有一个收藏夹按钮。单击它一次只会推送一次状态更新,任何后续单击都不会传播。视图本身也不会更新。就好像从来没有点击过一样。
现在将 AndroidView.update
的块更改为使用 it
并将其转换为具体的视图类型,如预期的那样工作。所有点击都正确传播并且卡片视图得到更新以反映状态。
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
// provider.setup(product, interactionListener)
(it as ProductCardView).setup(product, interactionListener)
}
}
}
}
我在这里错过了什么?为什么在将视图转换为它的类型时使用 ProductCard
不起作用?
更新 1
似乎转换为 ProductCard
也有效
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
// provider.setup(product, interactionListener)
(it as ProductCard).setup(product, interactionListener)
}
}
}
}
所以问题是为什么我们必须在 AndroidView.update
中使用 it
而不是对视图的任何其他引用?
这里的答案是我缺少 LazyColumn
项目所需的 key
值,以便 compose 知道哪个项目已更改并对其调用更新。
今天早上遇到了 AndroidView 的奇怪情况。
我有一个如下所示的 ProductCard 界面
interface ProductCard {
val view: View
fun setup(
productState: ProductState,
interactionListener: ProductCardView.InteractionListener
)
}
该接口可以由多个视图实现。
呈现 AndroidView
列表的可组合项使用 ProductCard
获取视图并在发生重组时传入状态更新。
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
provider.setup(product, interactionListener)
}
}
}
}
对于此示例,与 ProductCard 视图的任何交互(调用 ProductCard.setup()
)都不会更新屏幕。日志记录显示状态已更新,但要注意的是每个按钮仅更新一次。例如,我有一个收藏夹按钮。单击它一次只会推送一次状态更新,任何后续单击都不会传播。视图本身也不会更新。就好像从来没有点击过一样。
现在将 AndroidView.update
的块更改为使用 it
并将其转换为具体的视图类型,如预期的那样工作。所有点击都正确传播并且卡片视图得到更新以反映状态。
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
// provider.setup(product, interactionListener)
(it as ProductCardView).setup(product, interactionListener)
}
}
}
}
我在这里错过了什么?为什么在将视图转换为它的类型时使用 ProductCard
不起作用?
更新 1
似乎转换为 ProductCard
也有效
@Composable
fun BasketItemsList(
modifier: Modifier,
basketItems: List<ProductState>,
provider: ProductCard,
interactionListener: ProductCardView.InteractionListener
) {
LazyColumn(modifier = modifier) {
items(basketItems) { product ->
AndroidView(factory = { provider.view }) {
Timber.tag("BasketItemsList").v(product.toString())
// provider.setup(product, interactionListener)
(it as ProductCard).setup(product, interactionListener)
}
}
}
}
所以问题是为什么我们必须在 AndroidView.update
中使用 it
而不是对视图的任何其他引用?
这里的答案是我缺少 LazyColumn
项目所需的 key
值,以便 compose 知道哪个项目已更改并对其调用更新。