0

At first, itemBackgroundColor is correct, some items are blue and some are gray.

But when the list is updated and some item.judge changed, itemBackgroundColor won't update accordingly.

How can I update itemBackgroundColor when the list is updated? Thanks a lot!

@Composable
fun LayoutsCodelab(viewModel: MyViewModel) {
// list<Item>, Item contains name, judge
val list = viewModel.myList.observeAsState(listOf()).value

Scaffold {
    LazyColumn(state = rememberLazyListState()) {
        items(list.size) {
            val item = list[it]

            // How can I update itemBackgroundColor based on item.judge?
            val itemBackgroundColor by mutableStateOf(
                if (item.judge) Color.Blue else Color.Gray)
            
            // apply itemBackgroundColor  here
            Row(modifier = Modifier.background(color = itemBackgroundColor)) {
                //other detail codes ...
            }
        }
    }
}
}
caibirdcnb
  • 275
  • 5
  • 18

1 Answers1

0

First of all, refrain from using LiveData unless your use-case strictly requires so.

Inside your ViewModel, you can create a list like so,

class MVVM : ViewModel(){
 var itemsList = mutableStateListOf<Item>()
}

Then, inside your activity, you should probably not pass the entire viewmodel around, but that's totally up to you. So, in this case

@Composable
fun LayoutsCodelab(viewModel: MyViewModel) {
val list = viewModel.itemsList

Scaffold {
    LazyColumn(state = rememberLazyListState()) {
        items(list.size) {
            val item = list[it]

            // Don't use mutableStateOf willy-nilly,
            /*val itemBackgroundColor by mutableStateOf(
                if (item.judge) Color.Blue else Color.Gray)*/
            
            Row(modifier = Modifier.background(color = if(item.judge) ColorBlue else Color.Gray)) {
                //other detail codes ...
            }
        }
    }
}

You do not require mutableStateOf's usage at the place where you were calling it in your original code. Consider taking the State-in-Compose codelab to learn further.

Also, I think your code should have actually worked fine even without these modifications if the items were being rendered as per the updated list, but the problem (I am about 2/3 sure) may lie in the "other code details..." section, where the Composables present there may be taking up the entire space of the item, hence, hiding it's modified background. Consider applying this background Modifier to the children Composables over there as well and then check it is works out.

  • Thanks for the elaboration. But it doesn't work. Actually it won't even pass the grammar check, the list is a State, so cannot apply like [list.size], did you mean val list = viewModel.itemsList.value? – caibirdcnb Feb 27 '22 at 21:54
  • if so, it still not working. I figured that no State variable in this statement, how can the ui re-compose? "color = if(item.judge) ColorBlue else Color.Gray" – caibirdcnb Feb 27 '22 at 21:59
  • regarding the LiveData parts, actually the list came from room, and it is a Flow, I convert it to LiveData in viewModel class and then convert to State in UI-related class. How can I use State in room, or convert Flow to State directly? I also do not want to do the Flow-LiveData-State convertion, I just have to. – caibirdcnb Feb 27 '22 at 22:03
  • Ok I understand your issue here, but I think you are confused between the role of `State` holders here. And what exactly do you mean when you say "there's no state variable here"? The `item` variable depends on `viewModel.itemsList`, which is a state-holder and is used within the scope of this composable, so recompositions WILL occur if any changes are made to the list and if the UI needs to be changed. –  Feb 28 '22 at 08:24
  • About the grammar check, you can replace the declaration statement with this: `var itemsList by mutableStateListOf()` -- Just add the `by` delegate. –  Feb 28 '22 at 08:26
  • Please update on what's the output for my code that you are receiving. Did you try to apply the background to the children Composable over there? That is most likely the cause of your issue. –  Feb 28 '22 at 08:27
  • Stark, it is very kind of you! I think I understand your comment. But somehow it still doesn't work. In summary, if I delete/add/ a row in the db table, I do see the update on ui, but if I only update a field of a row, I checked the db table updated, but ui not update. – caibirdcnb Mar 03 '22 at 22:42
  • I made a demo in below link, could you help take a look please? Thanks a lot! https://stackoverflow.com/questions/71289865/lazycolumn-item-not-updated-accordingly-while-list-in-room-table-already-updated – caibirdcnb Mar 03 '22 at 22:43
  • I'll take a look at that, –  Mar 05 '22 at 07:40