Home > other >  Jetpack Compose deriveStateOf side effect cannot work along snapshotFlow side effect?
Jetpack Compose deriveStateOf side effect cannot work along snapshotFlow side effect?

Time:01-20

When I have the below code, all works (i.e. When scrolling past the first row, a button appears. When scrolling past the second row, another button appears)

@ExperimentalAnimationApi
@Composable
fun TestSnapshotFlow() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        val listState = rememberLazyListState()

        LazyColumn(state = listState) {
            items(1000) { index ->
                Text(text = "Item: $index")
            }
        }

        var showButtonSnapshot by remember {
            mutableStateOf(false)
        }

        val showButtonDerive by remember(listState.firstVisibleItemIndex) {
            mutableStateOf(
                listState.firstVisibleItemIndex > 0
            )
        }

        Log.d("Track", "Recompose")
        Column {
            AnimatedVisibility(showButtonDerive) {
                Button({}) {
                    Text("Row 1 hiding")
                }
            }
            AnimatedVisibility(showButtonSnapshot) {
                Button({}) {
                    Text("Row 1 and 2 hiding")
                }
            }
        }

        LaunchedEffect(listState) {
            snapshotFlow { listState.firstVisibleItemIndex }
                .map { index -> index > 2 }
                .distinctUntilChanged()
                .collect {
                    Log.d("Track", "B $it")
                    showButtonSnapshot = it
                }
        }
    }
}

However, If I change

val showButtonDerive by remember(listState.firstVisibleItemIndex) {
    mutableStateOf(
        listState.firstVisibleItemIndex > 0
    )
}

to the DeriveStateOf

val showButtonDerive by remember {
    derivedStateOf {
        listState.firstVisibleItemIndex > 0
    }
}

It doesn't work as expected anymore. The second button won't appear. (even though I check that the collect did trigger and and change showButtonSnapshot to true, the recomposition didn't happen anymore).

Looks like deriveStateOf and snapshotFlow can't work together to trigger the recompose. Separate them out individually works.

Just for easier copy-&-paste to test, the full code that doesn't work as expected as below

@ExperimentalAnimationApi
@Composable
fun TestSnapshotFlow() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        val listState = rememberLazyListState()

        LazyColumn(state = listState) {
            items(1000) { index ->
                Text(text = "Item: $index")
            }
        }

        var showButtonSnapshot by remember {
            mutableStateOf(false)
        }

        val showButtonDerive by remember {
            derivedStateOf {
                listState.firstVisibleItemIndex > 0
            }
        }

        Log.d("Track", "Recompose")
        Column {
            AnimatedVisibility(showButtonDerive) {
                Button({}) {
                    Text("Row 1 hiding")
                }
            }
            AnimatedVisibility(showButtonSnapshot) {
                Button({}) {
                    Text("Row 1 and 2 hiding")
                }
            }
        }

        LaunchedEffect(listState) {
            snapshotFlow { listState.firstVisibleItemIndex }
                .map { index -> index > 2 }
                .distinctUntilChanged()
                .collect {
                    Log.d("Track", "B $it")
                    showButtonSnapshot = it
                }
        }
    }
}

CodePudding user response:

It looks like you're doing everything right, and recomposition isn't triggered when it should. I suggest you report it.

As a tmp solution you can update the value from an other coroutine scope, for example from MainScope():

snapshotFlow { listState.firstVisibleItemIndex }
    .map { index -> index > 2 }
    .distinctUntilChanged()
    .collect {
        MainScope().launch {
            showButtonSnapshot = it
        }
    }
  •  Tags:  
  • Related