Jetpack compose with room does not perform onSuccess() action, however the data was inserted
This is my viewModel call from the screen fun:
DIRECTOR_ID = UUID.randomUUID()
AGENCY_ID = UUID.randomUUID()
viewModel.addDirectorAndAgency(
director = Director(
directorId = DIRECTOR_ID,
directorName = directorNameValue,
directorPhone = phoneValue,
directorPassword = directorPasswordValue,
agencyId = AGENCY_ID
),
agency = Agency(
agencyId = AGENCY_ID,
agencyName = agencyNameValue
)
) {
navController.navigate(Graph.MAIN) //This action is not completed
}
This is my viewmodel code:
fun addDirectorAndAgency(agency: Agency, director: Director, onSuccess: () -> Unit) {
viewModelScope.launch(Dispatchers.IO) {
REPOSITORY.insertDirectorAndAgency(agency = agency, director = director ) {
viewModelScope.launch(Dispatchers.Main) {
onSuccess()
}
}
}
}
Database repository:
suspend fun insertDirectorAndAgency(director: Director, agency: Agency, onSuccess: ()-> Unit)
RoomRepository
override suspend fun insertDirectorAndAgency(
director: Director,
agency: Agency,
onSuccess: () -> Unit
) {
agencyDao.insertDirectorAndAgency(agency = agency, director = director )
}
RoomDao:
@Transaction
suspend fun insertDirectorAndAgency(director: Director, agency: Agency) {
insertDirector(director)
insertAgency(agency)
}
You shouldn't write side effects in Compose, instead of waiting for a result in the Ui side with onSuccess
you can create a SharedFlow (hot flow) for navigation events in the ViewModel, along with a custom sealed class. Then you need to listen these events in the Compose screen.
in the ViewModel:
private val _navigationEvents = MutableSharedFlow<NavigationEvent>()
val navigationEvents = _navigationEvents.asSharedFlow()
Sealed class:
sealed class NavigationEvent {
object Main : NavigationEvent()
data class Detail(val id: String) : NavigationEvent() // sample
}
in the Compose screen:
@Composable
fun Screen(
navController: NavHostController,
viewModel: MainViewModel = hiltViewModel()
) {
LaunchedEffect(Unit) {
viewModel.navigationEvents.collect { event ->
when (event) {
Main -> navController.navigate(Graph.MAIN)
Detail -> // navigate with event.id
}
}
}
}
You can send the Main
navigation event to this flow on success in the viewModel, then your navigation should happen.