BlazeCodeDev
BlazeCodeDev

Reputation: 989

Jetpack compose change in uiState doesn't trigger recomposition

I think I haven't quite wrapped my head around how compose states work yet. I'm not able to trigger a recomposition when an item in the uiState changes.

I'm building an app that need notification access, so for that I'm navigating the user to the settings and after the user has granted permission they have to navigate back to the app. That's where I want to trigger the recomposition.

I have the permission check in onResume working and the variable in the uiState changes, but the recomposition doesn't get called. What am I missing here?

Composable

@Composable
private fun MainLayout(viewModel: SetupViewModel){
    val uiState = viewModel.uiState.collectAsState()
    SetupItem(
        title = "Notification access",
        summary = if(uiState.value.hasNotificationPermission) stringResource(R.string.granted) else stringResource(R.string.not_granted){}
}

SetupUiState.kt

data class SetupUiState(
    var hasNotificationPermission: Boolean = false
)

I know for a fact that hasNotificationPermission gets set to true, but the summary in the SetupItem does not update. How do I accomplish that?

Upvotes: 6

Views: 3023

Answers (1)

Jan Bína
Jan Bína

Reputation: 7188

The problem here is that the hasNotificationPermission field is mutable (var and not val). Compose is not tracking inner fields for change. You have two options here:

  1. Modify the SetupUiState as a whole, assuming you are using StateFlow in your ViewModel, it can look like this:
    fun setHasNotificationPermission(value: Boolean) {
        uiState.update { it.copy(hasNotificationPermission = value) }
    }
    
    You should also change hasNotificationPermission from var to val.
  2. You can make use of compose's State and do something like this:
    class SetupUiState(
        initialHasPermission: Boolean = false
    ) {
        var hasNotificationPermission: Boolean by mutableStateOf(initialHasPermission)
    }
    
    With this you can then simply do uiState.hasNotificationPermission = value and composition will be notified, since it's tracking State instances automatically.

Upvotes: 14

Related Questions