Reputation: 60081
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
}
}
}
}
Upvotes: 1
Views: 1160
Reputation: 87615
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
}
}
Upvotes: 1