Compose:LazyColumn 在单个项目更新时重新组合所有项目

Posted

技术标签:

【中文标题】Compose:LazyColumn 在单个项目更新时重新组合所有项目【英文标题】:Compose: LazyColumn recomposes all items on single item update 【发布时间】:2021-09-20 12:35:49 【问题描述】:

我正在尝试使用 LazyColumn 在列表中显示订单列表。代码如下:

@Composable
private fun MyOrders(
    orders: List<Order>?,
    onClick: (String, OrderStatus) -> Unit
) 
    orders?.let 
        LazyColumn 
            items(
                items = it,
                key =  it.id 
            ) 
                OrderDetails(it, onClick)
            
        
    


@Composable
private fun OrderDetails(
    order: Order,
    onClick: (String, OrderStatus) -> Unit
) 
    println("Composing Order Item")
    // Item Code Here

这就是方式,我称之为可组合:

orderVm.fetchOrders()
val state by orderVm.state.collectAsState(OrderState.Empty)

if (state.orders.isNotEmpty()) 
    MyOrders(state.orders) 
        // Handle status change click listener
    

我获取所有订单并显示在 LazyColumn 中。但是,当更新单个订单时,整个 LazyColumn 都会重新组合。这是我的 ViewModel 的样子:

class OrderViewModel(
    fetchrderUseCase: FetechOrdersUseCase,
    updateStatusUseCase: UpdateorderUseCase
) 

    val state = MutableStateFlow(OrderState.Empty)

    fun fetchOrders() 
        fetchrderUseCase().collect 
            state.value = state.value.copy(orders = it.data)
        
    

    fun updateStatus(newStatus: OrderStatus) 
        updateStatusUseCase(newStatus).collect 
            val oldOrders = status.value.orders
            status.value = status.value.copy(orders = finalizeOrders(oldOrders))
        
    

注意:finalizeOrders() 会根据 orderId 进行一些列表操作,以使用更新后的订单更新一个订单。

这就是我的状态:

data class OrderState(
    val orders: List<Order> = listOf(),
    val isLoading: Boolean = false,
    val error: String = ""
) 
    companion object 
        val Empty = FetchOrdersState()
    

如果我的数据库中有 10 个订单并且我更新了一个状态(比如说第 5 个项目),那么 OrderDetails 会被调用 20 次。不知道为什么。我可以对其进行优化以确保仅重组第 5 个索引项,并且仅使用新订单调用 OrderDetals

【问题讨论】:

【参考方案1】:

Orderclasss 稳定吗?如果不是,这可能是所有项目都被重新组合的原因:

如果所有输入稳定且未更改,Compose 会跳过可组合项的重组。比较使用equals方法

compose 文档中的This section 解释了什么是stable 类型以及如何跳过重组。

注意:如果你滚动一个惰性列表,所有不可见的项目都会被销毁。这意味着,如果您向后滚动,它们将被重新创建而不是重新组合(即使输入是 stable,您也不能跳过重新创建)。

【讨论】:

以上是关于Compose:LazyColumn 在单个项目更新时重新组合所有项目的主要内容,如果未能解决你的问题,请参考以下文章

Jetpack Compose LazyColumn 以编程方式滚动到项目

如何使用 JetPack Compose 在 LazyColumn 项目中单击导航到详细视图?

在jetpack compose LazyColumn中获取最后一个可见的项目索引

如何在 Jetpack Compose 中为 LazyColumn 设置默认滚动位置而没有任何反馈或动画

Android Compose - 平板电脑上的应用程序在使用 LazyColumn 时崩溃

Android Compose LazyColumn IllegalArgumentException:密钥已被使用