0

I have the following function in my ViewModel:

fun insertMovie(movie: Movie): Long {
    var movieId = 0L
    viewModelScope.launch {
        movieId = repository.insertMovie(movie)
        Log.i(LOG_TAG, "add movie with id $movieId within launch")
    }
    Log.i(LOG_TAG, "add movieId with id $movieId")
    return movieId
}

Then the following in the Dao:

@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insertMovie(movie: Movie): Long {
    return movieDao.insert(movie)
}

In my activity I am doing the following:

viewModel.viewModelScope.launch {               
  val movieId = viewModel.insertMovie(Movie(...))

The movieId is always 0. Above I have two logs, the one within the launch{} shows the right id, but the other shows 0. I don't know how to force the code in my activity to wait until the method completes.

DeKekem
  • 589
  • 10
  • 20
  • 2
    Make viewmodels's `insertMovie()` also suspend and invoke `repository.insertMovie(movie)` directly, without `launch()`. – broot Jul 04 '22 at 13:15
  • Beyond that, your first code snippet returns `dayId`, and we do not know what that is. – CommonsWare Jul 04 '22 at 13:30

1 Answers1

0

A launch statement just launches a coroutine. What happens inside the coroutine does not matter to the rest of the function, thats why the code after the launch statement gets executet immediately after the launch and will probably be done before your repository.insertMovie().

As broot already mentioned, you could make the whole insertMovie() function of your viewmodel suspend and launch a coroutine from your activity/fragment.

Another way would be to have some kind of flow or liveData that gets updated when your coroutine is done and let your view react to that. Here is a link to the documentation for StateFlow and SharedFlow: https://developer.android.com/kotlin/flow/stateflow-and-sharedflow

Tobias
  • 294
  • 3
  • 13
  • That Is right. As I already have a `launch` inside the activity, I have made the `insertMovie()` function suspend and it now works. Thanks a lot – DeKekem Jul 04 '22 at 17:31
  • but still how would you know if `insert` suspend function has completed or not? – Mr. Techie Jan 02 '23 at 13:08
  • @Mr.Techie that really depends on the context. You could for example just save your coroutine in a variable and call ```.join()```on it. This suspends your function until the coroutine is complete and code below will only be executed after. If you want more control over your coroutines (emit events, etc.) use flows. – Tobias Mar 14 '23 at 16:50