在Intent服务中使用协程

时间:2019-05-21 11:49:25

标签: android kotlin-coroutines

我的应用程序冻结有问题。

所以:

  1. 我有意向服务(这意味着所有人已经在另一个线程中)
  2. 我有一个用户列表。
  3. 我应该为每个用户下载照片,然后将其推送到另一个具有面部识别功能的云服务。

现在,我们正在使用此服务的试用版。因此它在一分钟内只能发送10个请求。我要顺序执行程序(简单版本)

但是在尝试下载用户的照片时,应用程序冻结。只有完成后,应用程序才能开始工作。希望您能理解我的解释。

这是简单的代码(我正在使用corotinues):

private val ioScope = CoroutineScope(Dispatchers.IO + Job())

IntentService的onCreate方法

override fun onCreate() {
    super.onCreate()

    ioScope.launch {
        Repository.getUserList().observeOnce(Observer { users ->
            users?.forEach { user ->
                addedNewUser(user)
            }                
        })
    }
}

添加了NewUser

 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),但它不会等待文件下载的时间。

谢谢您的光临!

更新(answer)

感谢所有试图帮助我的人!我认为我们发现了问题。 Repository.getUserList()-返回livedata。因此,当在观察者中启动suspend或runBlocking函数时,我看到了冻结。如果将其包裹在corotinues或新线程中,则可以正常工作:

    Repository.getUserList().observeOnce(Observer { users ->
        ioScope.launch {
            users?.forEach { user ->
                addedNewUser(user)
            }   
        }.start()
    })

不幸的是,我不知道它在幕后如何工作的所有细节,但是看来,观察者在主线程中返回了值。因此,suspend函数只是停止了主线程。

0 个答案:

没有答案