Android kotlin сопрограммы, поведение viewModelScope - PullRequest
0 голосов
/ 17 июня 2020

У меня интересная проблема. Мне нужно поработать сразу после вставки, но viewModelScope случайным образом или, по крайней мере, выглядит случайным образом, пропускает функции, кроме первой.

Пример:

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

Итак, в этом Пример: все работает нормально только после установки fre sh приложения, но затем при следующем запуске приложения вторая функция «УвеличитьСумма» будет случайно пропущена, и я не знаю почему. И неважно, что будет после первой функции. Я пробовал простой «Журнал», и он тоже пропускается. Это нормально для viewModelScope?

РЕДАКТИРОВАТЬ Проверено на исключения. Вторая функция выдает исключение, что задание было отменено:

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

Кроме того, в моем фрагменте это вызывается так:

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

Итак, после вызова этой функции я go назад к предыдущему фрагменту. Возможно ли, что viewModel будет уничтожен до того, как закончит выполнение всей работы?

1 Ответ

1 голос
/ 17 июня 2020

Это нормально для viewModelScope?

Нет, это не так. В сопрограммах вызов функций должен быть последовательным. Функции itemsRepository.insertItem(item) и increaseAmount(item.catId) должны вызываться одна за другой. Я вижу несколько причин, по которым вторая функция не вызывается:

  1. Функция itemsRepository.insertItem(item) выдает какое-то исключение.
  2. Текущая область действия сопрограммы отменяется перед вызовом второй функции.

Edit :

ViewModel объекты имеют область видимости Lifecycle, переданную ViewModelProvider при получении ViewModel. ViewModel остается в памяти до тех пор, пока Lifecycle не исчезнет навсегда: в случае действия, когда оно завершается, а в случае фрагмента, когда оно отсоединяется.

После вас вызовите root.findNavController().popBackStack(), ваш фрагмент будет отсоединен, ViewModel очищен и задание сопрограммы отменено. Вы можете инициализировать ViewModel во фрагменте следующим образом:

private val viewModel: YourViewModel by activityViewModels()

Инициализируя viewModel таким образом, он будет привязан к Lifecycle из Activity.

Чтобы использовать activityViewModels(), добавьте следующую строку к зависимостям файла build.gradle приложения:

implementation "androidx.fragment:fragment-ktx:1.2.5"
...