0

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)
}

1 Answers1

0

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.