Aviran
Aviran

Reputation: 5458

Jetpack Compose rememberSwipeableState recycling issue

I have a LazyColumn that's generating items from a list data structure, every item has a swipeable state. Once an item is deleted from the list (Data structure), it is also reflected in UI, a recomposition is initiated and the LazyColumn is updated - not showing the deleted item - Correctly.

The problem is, all the swipe state variables of the LazyColumn items remain as before the deletion, For example, if the list was red, green, blue and green is deleted, the swipe state of green which was 2nd in the list is now the swipe state of blue which is now second in the list. All the items shift left, but the states remain in place.

Here's the code:


var dailyItems= viewModel.getItems().observeAsState(initial = emptyList())

LazyColumn(...) {
   items(dailyItems) { item ->
                SomeItem(
                    item = item,
                )
            }
}

SomeItem has a swipeable sub component in it

@Composable
private fun SomeItem(
  item: Item
) {

    val swipeState = rememberSwipeableState(
        initialValue = ItemState.HIDDEN,
        confirmStateChange = {
            onActionsReveal(item.id) // Note the use if item instance
            true
        }
    )



   Box(
        Modifier.swipeable(
            state = swipeState,
            anchors = anchors,
            orientation = Orientation.Horizontal,
            enabled = true,
            reverseDirection = isRtl
        )
    ) {
      ...
    }
}

 val swipeState = rememberSwipeableState()

val swipeState is recreated when SomeItem is re-composed, I see a new memory address for assigned to it, I also see that item.id is different.

But either confirmStateChange is not being overridden or the previous instance of swipeState is referenced somehow in future invocations - When the confirmStateChange is invoked - it always refers to the initial item.id

Upvotes: 2

Views: 774

Answers (1)

Aviran
Aviran

Reputation: 5458

Issue was solve by applying rememberUpdatedState to item.id


val id by rememberUpdatedState(item.id)

val swipeState = rememberSwipeableState(
        initialValue = ItemState.HIDDEN,
        confirmStateChange = {
            onActionsReveal(id)
            true
        }
    )

Upvotes: 2

Related Questions