1

I am having this interesting problem. I need to do some work immediately after insertion, but viewModelScope randomly, or at least it looks like randomly, skips functions except for the first one.

Example:

fun insertItem(item: SingleItem) = viewModelScope.launch {
        itemsRepository.insertItem(item)
        increaseAmount(item.catId)
    }

So in this example everything runs ok only after fresh app install, but then on the next app launches second function "increaseAmount" will be randomly skipped and i don`t know why. And it doesn't matter what goes after first function. I tried simple "Log" and it gets skipped as well. Is it normal for viewModelScope?

EDIT Checked for exceptions. Second function throws an exception that the job was cancelled:

kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}@2d87ff

Also, in my Fragment it is called like this:

viewModel.insertItem(newItem)
root.findNavController().popBackStack()

So after calling this function i go back to previous Fragment. Is it possible that viewModel gets destroyed before it finishes executing all work?

2
  • itemRepository.insertItem may throw exception. Have you checked it? Commented Jun 17, 2020 at 17:49
  • I am facing same issue, in my case after install on first run Skip viewmodelscope.launch code block. If you solved this, than can you explain how you did it? Commented Jan 10, 2024 at 6:15

1 Answer 1

2

Is it normal for viewModelScope?

No, it is not. In coroutines functions call must be sequential. Functions itemsRepository.insertItem(item) and increaseAmount(item.catId) must be called one after another. I see a couple of reasons why second function is not called:

  1. Function itemsRepository.insertItem(item) throws some exception.
  2. Current coroutine scope is cancelled before second function call.

Edit:

ViewModel objects are scoped to the Lifecycle passed to the ViewModelProvider when getting the ViewModel. The ViewModel remains in memory until the Lifecycle it's scoped to goes away permanently: in the case of an activity, when it finishes, while in the case of a fragment, when it's detached.

After you call root.findNavController().popBackStack() your fragment will be detached, the ViewModel cleared and coroutine job cancelled. You can initialize the ViewModel in the fragment in the following way:

private val viewModel: YourViewModel by activityViewModels()

Initializing viewModel in this way it will be scoped to the Lifecycle of an Activity.

To use activityViewModels() add next line to the dependencies of app's build.gradle file:

implementation "androidx.fragment:fragment-ktx:1.2.5"
Sign up to request clarification or add additional context in comments.

3 Comments

ok, so i checked for exceptions. The first function doesn't throw any but the second, throws that a job was indeed cancelled. How to check why was it cancelled?
in Android Studio you can check exceptions in logcat
the only exception i can see is the one i mentioned above and only after i display it with try/catch

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.