Nickaleush
Nickaleush

Reputation: 5

Jetpack compose onSuccess() with insert into Room DB

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

Upvotes: 0

Views: 324

Answers (1)

yusufarisoy
yusufarisoy

Reputation: 91

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.

Upvotes: 0

Related Questions