当包含对象内部发生更改时,Jetpack Compose LazyColum 状态不会更改

发布于 2025-01-21 03:11:59 字数 3458 浏览 5 评论 0原文

下面是一个简单的购物车实现,如果单击列表项目,则应增加数量的值,

但在ui中以某种方式变化,但不反映在UI中(不使用使用新的数量值)

我认为问题在于这一部分: lazycolumn {items(cartinfo.value !!。cartitems){...}

作为cartitems不是直接的状态值,这就是为什么不触发lazycolumn ui的重组的原因。

但是不能将此问题解决为mutableStateof< cartinfo?>是固定的,我不希望mutableStist< cartitem>单独的

data class User(var id: String, var name: String)
data class Product(var id: String, var name: String)
data class CartItem(var product: Product, var qty: Int)
data class CartInfo(val userid: String, val cartItems: MutableList<CartItem>)

val user = User("1", "A")
val item1 = CartItem(Product("1", "iPhone"), 1)
val item2 = CartItem(Product("2", "Xbox"), 1)
val cart = CartInfo(user.id, mutableListOf(item1, item2))

class MainViewModel : ViewModel() {
    private val _cartInfo = mutableStateOf<CartInfo?>(null)
    val cartInfo: State<CartInfo?> = _cartInfo

    init {
        _cartInfo.value = cart
    }

    fun increaseQty(product: Product, user: User) {
        viewModelScope.launch {
            var cartInfo = cartInfo.value

            if (user.id == cartInfo?.userid) {
                var cartItems = cartInfo.cartItems.map {
                    if (it.product.id == product.id) {
                        it.qty += 1
                        it
                    } else
                        it
                }
                _cartInfo.value = cartInfo.copy(cartItems = cartItems as MutableList<CartItem>)
            }
//            Log.d("debug", "viewmodel: ${cartInfo?.cartItems.toString()}")
        }
    }

}


class MainActivity : ComponentActivity() {
    private val viewModel by viewModels<MainViewModel>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    val cartInfo = viewModel.cartInfo
                    Log.d("debug", cartInfo.toString())

                    LazyColumn {
                        items(cartInfo.value!!.cartItems) {
                            Card(modifier = Modifier
                                .fillMaxWidth()
                                .padding(5.dp)
                                .clickable {
                                    viewModel.increaseQty(it.product, user)
                                }) {
                                Row() {
                                    Text(
                                        text = "${it.product.name}",
                                        modifier = Modifier.weight(1f).padding(10.dp)
                                    )
                                    Text(
                                        text = "qty: ${it.qty}"
                                    )
                                }

                            }

                        }
                    }
                }
            }
        }
    }
}

状态

enter image description here

Below is a simple Cart Implementation where the value of qty should increase by 1 if a list item is clicked...

But somehow values in the ViewModel are changing, but not reflected in UI ( not recomposing with new qty value)

I think problem lies in this part :
LazyColumn {items(cartInfo.value!!.cartItems){...}

as cartItems is not directly a state value that's why not triggering the recomposition of the LazyColumn UI.

But cant solve this problem as mutableStateOf<CartInfo?> is fixed and I don't want a separate state for MutableList<CartItem>

data class User(var id: String, var name: String)
data class Product(var id: String, var name: String)
data class CartItem(var product: Product, var qty: Int)
data class CartInfo(val userid: String, val cartItems: MutableList<CartItem>)

val user = User("1", "A")
val item1 = CartItem(Product("1", "iPhone"), 1)
val item2 = CartItem(Product("2", "Xbox"), 1)
val cart = CartInfo(user.id, mutableListOf(item1, item2))

class MainViewModel : ViewModel() {
    private val _cartInfo = mutableStateOf<CartInfo?>(null)
    val cartInfo: State<CartInfo?> = _cartInfo

    init {
        _cartInfo.value = cart
    }

    fun increaseQty(product: Product, user: User) {
        viewModelScope.launch {
            var cartInfo = cartInfo.value

            if (user.id == cartInfo?.userid) {
                var cartItems = cartInfo.cartItems.map {
                    if (it.product.id == product.id) {
                        it.qty += 1
                        it
                    } else
                        it
                }
                _cartInfo.value = cartInfo.copy(cartItems = cartItems as MutableList<CartItem>)
            }
//            Log.d("debug", "viewmodel: ${cartInfo?.cartItems.toString()}")
        }
    }

}


class MainActivity : ComponentActivity() {
    private val viewModel by viewModels<MainViewModel>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    val cartInfo = viewModel.cartInfo
                    Log.d("debug", cartInfo.toString())

                    LazyColumn {
                        items(cartInfo.value!!.cartItems) {
                            Card(modifier = Modifier
                                .fillMaxWidth()
                                .padding(5.dp)
                                .clickable {
                                    viewModel.increaseQty(it.product, user)
                                }) {
                                Row() {
                                    Text(
                                        text = "${it.product.name}",
                                        modifier = Modifier.weight(1f).padding(10.dp)
                                    )
                                    Text(
                                        text = "qty: ${it.qty}"
                                    )
                                }

                            }

                        }
                    }
                }
            }
        }
    }
}

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风流物 2025-01-28 03:11:59

在此行中,_cartinfo.value = Cartinfo您在_cartinfo中设置了相同的对象。

可变状态无法检查内部对象的状态是否已更改,它只能检查它是否是同一对象。

您可以使您的Cartinfo一个数据类,该类别可轻松创建一个使用复制的新对象。确保您不使用任何var或修改的收集,例如mutablelist来减少错误的机会。查看为什么不可变性在功能编程中很重要?

data class CartInfo(val id: String, val cartItems: List<Item>)

// usage
_cartInfo.value = cartInfo.copy(cartItems = cartItems)

In this line _cartInfo.value = cartInfo you set the same object in your _cartInfo.

Mutable state cannot check if the state of your internal object has changed, it can only check if it is the same object or not.

You can make your CartInfo a data class which allows you to easily create a new object with copy. Make sure you do not use any var or modifiable collections such as MutableList to reduce the chance of error. Check out Why is immutability important in functional programming?.

data class CartInfo(val id: String, val cartItems: List<Item>)

// usage
_cartInfo.value = cartInfo.copy(cartItems = cartItems)
听风吹 2025-01-28 03:11:59

使用Cartitem(it.product,qty = it.qty + 1)创建新的cartitem解决了问题:

fun increaseQty(product: Product, user: User) {
        viewModelScope.launch {
            var cartInfo = cartInfo.value

            if (user.id == cartInfo?.userid) {
                var cartItems = cartInfo.cartItems.map {
                    if (it.product.id == product.id) {
//                        old:
//                        it.qty += 1
//                        it
//                       changes made:
                        CartItem(it.product, qty = it.qty + 1)
                    } else
                        it
                }
                _cartInfo.value = cartInfo.copy(cartItems = cartItems as MutableList<CartItem>)
            }
        }
}

Creating new CartItem with CartItem(it.product, qty = it.qty + 1) solved the problem:

fun increaseQty(product: Product, user: User) {
        viewModelScope.launch {
            var cartInfo = cartInfo.value

            if (user.id == cartInfo?.userid) {
                var cartItems = cartInfo.cartItems.map {
                    if (it.product.id == product.id) {
//                        old:
//                        it.qty += 1
//                        it
//                       changes made:
                        CartItem(it.product, qty = it.qty + 1)
                    } else
                        it
                }
                _cartInfo.value = cartInfo.copy(cartItems = cartItems as MutableList<CartItem>)
            }
        }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文