Home > Net >  use 'mutableState' value in init of viewmodel
use 'mutableState' value in init of viewmodel

Time:06-15

i defined a var showAllEvent = mutableStateOf(false) in my viewmodel and want to use it in init {} of my viewmodel, but when use, give me this error: IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied how can i use my value in init of my viewmodel` in jetpack compose

@HiltViewModel
class EventPageVM @Inject constructor(
private val repository: EventRepository,
private val noteRepository: NoteRepository
) : ViewModel() {

private val _eventsList = MutableStateFlow<List<Event>>(emptyList())
val eventsList = _eventsList.asStateFlow()
///
var showAllEvent = mutableStateOf(false)
var showPastEvent = mutableStateOf(true)


init {
    viewModelScope.launch(Dispatchers.IO) {
        val fromTo = Extra.getFromToNextMonth(CivilDate())
        val start= if (showPastEvent.value)null else fromTo[0]
        val end=if (showAllEvent.value)null else fromTo[1]
        repository.getEvents(start, end).distinctUntilChanged().collect { result ->
            _eventsList.value = result
        }
    }

}

CodePudding user response:

I guess states created using mutableStateOf should be written/read from the UI thread. Currently you use Dispatchers.IO which means that the state is read in the background thread. Try to use Dispatchers.Main context in code where you work with the state:

init {
    viewModelScope.launch {
        val fromTo = Extra.getFromToNextMonth(CivilDate())
        val start = if (showPastEvent.value) null else fromTo[0]
        val end = if (showAllEvent.value) null else fromTo[1]
        repository.getEvents(start, end).distinctUntilChanged().collect { result ->
            _eventsList.value = result
        }
    }
}

viewModelScope.launch by default uses Dispatchers.Main context.

Another approach is to use Flows in the ViewModel and collect them in the Compose functions.

CodePudding user response:

I had the same exact issue and opted to move initialization to a LaunchedEffect in a Jetpack Compose project. Though the approach of initializing state in the init block seemed useful at first it became a pain when attempting to run instrumented tests.

Here's a lengthy write up on the subject: https://jetc.dev/slack/2022-05-16-mutating-state-viewmodel-constructor.html

  • Related