Search code examples
kotlinrx-java2

IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet


Assume simplfied class like:

class MyModel() {

    companion object

    val number = mutableStateOf(0)

    init {
        refresh()
    }

    fun refresh() {

        RestClient.getNumber()
            .doOnNext { i ->
                number.value = i
            }
            .take(1)
            .subscribe()
    }
}

which I instantiate somewhere else:

val myModel = remember {
        MyModel()
}

sometimes I get:

Caused by: java.lang.IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied at androidx.compose.runtime.snapshots.SnapshotKt.readError(Snapshot.kt:1865) at androidx.compose.runtime.snapshots.SnapshotKt.current(Snapshot.kt:2171) at androidx.compose.runtime.SnapshotMutableStateImpl.setValue(SnapshotState.kt:299) at com.example.MyModel$refresh$4.accept(MyModel.kt:14)

How can I avoid mentioned IllegalStateException?


Solution

  • The illegalStateException you are encountering is likely due to a concurrency issue, to avoid this issue, you should ensure that the state updates are performed in a way that is compatible with compose's lifecycle.

    class MyModel : ViewModel() {
        val number by mutableStateOf(0)
    
        init {
            refresh()
        }
    
        fun refresh() {
            viewModelScope.launch(Dispatchers.IO) {
                val newNumber = RestClient.getNumber()
                // Update the state on the UI thread
                viewModelScope.launch(Dispatchers.Main) {
                    number.value = newNumber
                }
            }
        }
    }