简体   繁体   中英

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. I have a iOS background with lots of SwiftUI though.

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:

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.

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. 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:

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)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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