简体   繁体   English

带有 LiveData 和 MutableList 的 ViewModel 未在 Jetpack Compose 中更新

[英]ViewModel with LiveData and MutableList not Updating in Jetpack Compose

Am new to Android Development in general and especially with Jetpack Compose and its ways of updating the Composables.我是 Android 总体开发的新手,尤其是 Jetpack Compose 及其更新可组合件的方法。 I have a iOS background with lots of SwiftUI though.我有一个 iOS 背景,但有很多 SwiftUI。

Anyways, I have the following app无论如何,我有以下应用程序

在此处输入图像描述

The Composables look like this:可组合项看起来像这样:

@Composable
fun Greeting() {
    Column(
        modifier = Modifier
            .fillMaxHeight()2
            .fillMaxWidth(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.SpaceEvenly
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceEvenly
        ) {
            IncrementButton()
            DecrementButton()
        }
        PressedText()
        SizeText()
    }
}

@Composable
fun PressedText() {
    val myViewModel: MyViewModel = viewModel()
    val myNumber by myViewModel.number.observeAsState()
    Text(text = "Pressed: $myNumber")
}

@Composable
fun SizeText() {
    val myViewModel: MyViewModel = viewModel()
    val myList by myViewModel.list.observeAsState()
    Text(text = "Size: ${myList?.size}")
}

@Composable
fun IncrementButton() {
    val myViewModel: MyViewModel = viewModel()
    Button(onClick = myViewModel::add) {
        Text("Add")
    }
}

@Composable
fun DecrementButton() {
    val myViewModel: MyViewModel = viewModel()
    Button(onClick = myViewModel::remove) {
        Text("Remove")
    }
}

The view model I am using looks like this:我正在使用的视图 model 如下所示:

class MyViewModel : ViewModel() {
    private val _number = MutableLiveData<Int>()
    val number: LiveData<Int> = _number

    private val _list = MutableLiveData<MutableList<Int>>()
    val list: LiveData<MutableList<Int>> = _list

    init {
        _number.value = 0
        _list.value = mutableListOf()
    }

    fun add() {
        _number.value = _number.value?.plus(1)
        _number.value?.let {
            _list.value?.add(it)
            _list.value = _list.value
        }
    }

    fun remove() {
        _number.value = _number.value?.minus(1)
        if (_list.value?.isNotEmpty() == true) {
            _list.value?.removeAt(0)
            _list.value = _list.value
        }
    }
}

When I press the "Add"-button the number after "Pressed" gets updated but not the number after "Size".当我按下“添加”按钮时,“按下”后的数字会更新,但“大小”后的数字不会更新。

Am really not sure about those lines with _list.value = _list.value that I have from some other SO post that said to update the reference of the list.我真的不确定那些带有_list.value = _list.value的行,我从其他一些 SO 帖子中得到的,这些帖子说要更新列表的引用。

What am I missing?我错过了什么? Any hints highly appreciated.任何提示高度赞赏。

Feel free to leave any comments regarding code design.请随时留下有关代码设计的任何评论。

Thank you!谢谢!

This _list.value = _list.value is a really bad idea.这个_list.value = _list.value是一个非常糟糕的主意。 Depending on underlying implementation, it may work or may not.根据底层实现,它可能有效也可能无效。 In this case it's probably compared by pointer, that's why it doesn't trigger recomposition.在这种情况下,它可能通过指针进行比较,这就是它不会触发重组的原因。

Check out Why is immutability important in functional programming .查看为什么不变性在函数式编程中很重要

The safe way is using non mutable list:安全的方法是使用非可变列表:

private val _list = MutableLiveData<List<Int>>()

And mutate it like this:并像这样改变它:

_list.value = _list.value?.toMutableList()?.apply {
    add(value)
}

By doing this, you're creating a new list each time, and this will trigger recomposition without problems.通过这样做,您每次都会创建一个新列表,这将毫无问题地触发重组。


Also, using LiveData is not required at all: if you don't have some dependencies, which makes you using it, you can go for Compose mutable state: it's much cleaner:此外,根本不需要使用LiveData :如果您没有某些依赖项,这会让您使用它,您可以将 go 用于 Compose 可变 state:它更干净:

var number by mutableStateOf(0)
    private set

private val _list = mutableStateListOf<Int>()
val list: List<Int> = _list

fun add() {
    number++
    _list.add(number)
}

fun remove() {
    number--
    _list.removeAt(0)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM