Composable not recomposing when list is cleared in jetpack compose

Issue

I have one MutableStateFlow which is kind of emptyList. When I add the item my view is recomposed without any problem. Now I want to recompose view when list is clear. I tried some piece of code but nothing happens.

PairViewModel

class PairViewModel : BaseViewModel() {
     val scanLowEnergyDevices by lazy { MutableStateFlow(emptyList<ScanResult>()) }

     fun addDevices(result: ScanResult) {
        scanLowEnergyDevices.value += result
    }
}

ContentStateful

@Composable
fun ContentStateful(
    context: Context = LocalContext.current,
    viewModel: BloodPressurePairViewModel = getViewModel()
) {
    val activity = context as ComponentActivity
    val scanDeviceList by viewModel.scanLowEnergyDevices.collectAsStateWithLifecycle()
  
    ContentStateLess(
        scanDeviceList = scanDeviceList,
        resetAction = {
            viewModel.scanLowEnergyDevices.value.toMutableList().clear()
        }   
    )
}

ContentStateLess

@Composable
fun ContentStateLess(
    scanDeviceList: List<ScanResult>,
    resetAction: () -> Unit,
) {
    AnimatedVisibility(visible = scanDeviceList.isNotEmpty()) {
        Text(text = "scanDeviceList ${scanDeviceList.size}")
        Button(onClick = { resetAction() }) {
            Text(text = "Reset")
        }
    }
}

What is wrong in here? Thanks

Solution

Try to use SnapshotStateList like this

val scanLowEnergyDevices by lazy { mutableStateListOf<ScanResult>() }

add items like this

fun addDevices(result: ScanResult) {
    scanLowEnergyDevices.add(result)
    // scanLowEnergyDevices.value.add(result)
}

and clear the list like you would do with a standard collection like this

resetAction = {
    viewModel.scanLowEnergyDevices.clear()
    // viewModel.scanLowEnergyDevices.value.clear()
} 

or in your use-case, since its wrap inside a State, just call the .value before the .add() and .clear() calls

Answered By – z.y

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *