Использование сопрограмм в сервисе Intent - PullRequest
0 голосов
/ 21 мая 2019

У меня проблема с зависанием моего приложения.

Итак:

  1. У меня есть служба намерений (это означает, что все уже в другой теме)
  2. У меня есть список пользователей.
  3. Я должен загрузить фотографии для каждого пользователя и отправить их в другой облачный сервис (с распознаванием лиц).

Сейчас мы используем пробную версию этого сервиса. Таким образом, он может отправлять только 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()
    })

К сожалению, я не знаю всех деталей, как это работает под капотом, но кажется, что наблюдатель возвращает значение в главном потоке. Так что функция приостановки просто остановила основной поток.

...