Sparsh Dutta
Sparsh Dutta

Reputation: 3008

Recomposition does not happen on change of value of mutableList()

I am using a LazyColumn to populate items on my screen. I have a mutablelist(), and a Text composable, which is a part of a LazyColumn item, is created based on the value of my mutable list for the index of that item. But on using debugger, it's clear that my Text composable is not getting recomposed on change of value of mutable list. This is my code:

        var listItemsOpen = remember { mutableListOf<Boolean>() }
        listItemsOpen.clear()
        for (i in 0..17){
            listItemsOpen.add(i, false)
        }

        LazyColumn(Modifier
                .constrainAs(listQuestions)
                {
                    start.linkTo(glListQuestionsLeft)
                    end.linkTo(glListQuestionsRight)
                    top.linkTo(glListQuestionsTop)
                    bottom.linkTo(glListQuestionsBottom)
                    width = Dimension.fillToConstraints
                    height = Dimension.fillToConstraints
                }
                .alpha(if (isAnyCategoryClicked) 1f
                else 0f))
        {
            itemsIndexed(if (txtToDisplay == "GENERAL") listGeneral
             else if (txtToDisplay == "PRIVACY, SAFETY & SECURITY") listPrivacy
            else if (txtToDisplay == "MY MONEY") listMyMoney
            else if (txtToDisplay == "WITHDRAWAL") listWithdrawal
            else listVoodleeAccSet
            ) { index, item ->
                Column(
                        Modifier
                                .padding(
                                        start = with(LocalDensity.current) { dimensionResource(id = R.dimen._9sdp) },
                                        end = with(LocalDensity.current) { dimensionResource(id = R.dimen._9sdp) },
                                        top = with(LocalDensity.current) { dimensionResource(id = R.dimen._12sdp) },
                                        bottom = with(LocalDensity.current) { dimensionResource(id = R.dimen._12sdp) },
                                )
                                .clickable {
                                    listItemsOpen[index] = !listItemsOpen[index]


                                    if (listItemsOpen[index]) {
                                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                            listItemsOpen.replaceAll { false }
                                        }
                                        listItemsOpen[index] = true

                                    }
                                }
                                .fillMaxWidth()
                                .background(Color(0xFF000000))
                )
                {

                    Box(Modifier
                            .fillMaxWidth()
                            .padding(
                                    start = with(LocalDensity.current) { dimensionResource(id = R.dimen._9sdp) },
                                    end = with(LocalDensity.current) { dimensionResource(id = R.dimen._9sdp) },
                                    top = with(LocalDensity.current) { dimensionResource(id = R.dimen._12sdp) },
                                    bottom = with(LocalDensity.current) { dimensionResource(id = R.dimen._12sdp) },
                            )) {
                        Text(
                                text = if (txtToDisplay == "GENERAL") stringResource(id = R.string.general_que1)
                                else if (txtToDisplay == "PRIVACY, SAFETY & SECURITY") stringResource(
                                        id = R.string.privacy_que1
                                )
                                else if (txtToDisplay == "MY MONEY") stringResource(id = R.string.my_money_que1)
                                else if (txtToDisplay == "WITHDRAWAL") stringResource(id = R.string.withdrawal_que1)
                                else stringResource(id = R.string.voodlee_acc_set_que1),
                                color = colorResource(id = R.color.bright_green),
                                fontSize = with(LocalDensity.current) {
                                    dimensionResource(id = R.dimen._11ssp).toSp()
                                },
                                fontFamily = FontFamily(
                                        Font(R.font.poppins_regular)
                                ),
                                textAlign = TextAlign.Center,
                                modifier = Modifier.align(CenterStart)
                        )

                        Image(
                                painter = painterResource(id = R.drawable.ic_faq_dn),
                                modifier = Modifier
                                        .align(CenterEnd)
                                        .height(with(LocalDensity.current) { dimensionResource(id = R.dimen._22sdp) })
                                        .width(with(LocalDensity.current) { dimensionResource(id = R.dimen._22sdp) }),
                                contentDescription = "ic down"
                        )

                        Image(
                                painter = painterResource(id = R.drawable.ic_faq_up),
                                modifier = Modifier
                                        .align(CenterEnd)
                                        .height(with(LocalDensity.current) { dimensionResource(id = R.dimen._22sdp) })
                                        .width(with(LocalDensity.current) { dimensionResource(id = R.dimen._22sdp) }),
                                contentDescription = "ic up"
                        )

                    }

                    Spacer(modifier = Modifier.height(with(LocalDensity.current) {
                        dimensionResource(id = R.dimen._6sdp)
                    }))


               **//BELOW TEXT COMPOSABLE IS NOT GETTING RECOMPOSED**

                    if (listItemsOpen[index]) {

                        Text(
                                text = if (txtToDisplay == "GENERAL") stringResource(id = R.string.general_ans1)
                                else if (txtToDisplay == "PRIVACY, SAFETY & SECURITY") stringResource(id = R.string.privacy_ans1)
                                else if (txtToDisplay == "MY MONEY") stringResource(id = R.string.my_money_ans1)
                                else if (txtToDisplay == "WITHDRAWAL") stringResource(id = R.string.withdrawal_ans1)
                                else stringResource(id = R.string.voodlee_acc_set_ans1),
                                color = colorResource(id = R.color.bright_green),
                                fontSize = with(LocalDensity.current) {
                                    dimensionResource(id = R.dimen._11ssp).toSp()
                                },
                                fontFamily = FontFamily(
                                        Font(R.font.poppins_light)
                                ),
                                textAlign = TextAlign.Center,
                        )
                    }
                }
            }
        }

How do I make the above Text recompose when the value of mutable list for that index changes?

Upvotes: 3

Views: 1745

Answers (1)

Richard Onslow Roper
Richard Onslow Roper

Reputation: 6863

Recompositions take place only on modification of state holders. The docs discourage the use of stuff like mutableListOf(...) to store state in your app. You should instead use pre-defined state-holders.

Just change the declaration to

var listItemsOpen by remember { mutableStateOf(listOf<Boolean>()) }

The docs:-

_Caution: Using mutable objects such as ArrayList or mutableListOf() as state in Compose will cause your users to see incorrect or stale data in your app.

Mutable objects that are not observable, such as ArrayList or a mutable data class, cannot be observed by Compose to trigger recomposition when they change.

Instead of using non-observable mutable objects, we recommend you use an observable data holder such as State<List> and the immutable listOf()._

Upvotes: 2

Related Questions