У меня проблема с зависанием моего приложения.
Итак:
- У меня есть служба намерений (это означает, что все уже в другой теме)
- У меня есть список пользователей.
- Я должен загрузить фотографии для каждого пользователя и отправить их в другой облачный сервис (с распознаванием лиц).
Сейчас мы используем пробную версию этого сервиса. Таким образом, он может отправлять только 10 запросов в минуту. Я хочу последовательное выполнение программы (простая версия)
Но приложение зависает при попытке загрузить фотографии пользователя. Только после завершения приложение начинает работать. Я надеюсь, вы понимаете мое объяснение.
Вот простой код (я использую для этого corotinues):
private val ioScope = CoroutineScope(Dispatchers.IO + Job())
onCreate метод IntentService
override fun onCreate() {
super.onCreate()
ioScope.launch {
Repository.getUserList().observeOnce(Observer { users ->
users?.forEach { user ->
addedNewUser(user)
}
})
}
}
addedNewUser
private suspend fun addedNewUser(user: User) = withTimeoutOrNull(TWO_MINUTES) {
user.mail ?: return@withTimeoutOrNull
launch {
try {
// withContext is freez place
val file = withContext(ioScope.coroutineContext) { getUserAvatar(applicationContext, user.mail) }
// do something.......
file.delete()
} catch (e: ClientException) { // in free price mode face api allow only 20 requests in minutes
delay(ONE_MINUTE)
}
}.join()
}
У вас есть идеи? Почему withContext(Dispatchers.Default)
замерзает?
Также я попробовал withContext(this.coroutineContext)
, но он не ждет, когда файл будет загружен.
Спасибо за ваше время!
ОБНОВЛЕНИЕ (ответ)
Спасибо всем, кто пытался мне помочь! Я думаю, что мы нашли проблему. Repository.getUserList()
- вернуть livedata
. Поэтому, когда в обозревателе запускалась функция suspend или runBlocking, я наблюдал замораживание. Если это завернуто в corotinues или новую нить, это работает правильно:
Repository.getUserList().observeOnce(Observer { users ->
ioScope.launch {
users?.forEach { user ->
addedNewUser(user)
}
}.start()
})
К сожалению, я не знаю всех деталей, как это работает под капотом, но кажется, что наблюдатель возвращает значение в главном потоке. Так что функция приостановки просто остановила основной поток.