执行位图操作时 CoroutineWorker 中的 OOM

OOM in CoroutineWorker when doing Bitmap operations

提问人:StayCool 提问时间:7/12/2023 最后编辑:JemshitStayCool 更新时间:7/12/2023 访问量:54

问:

我正在尝试为一组文件(~2000)运行一些工作,我需要解码一些文件,因此需要大量内存。如果我像那样“做工作”:

override suspend fun doWork(): Result {
     (0...2000).forEach { i ->
         analyze(uris[i])
       }
     return Result.success()
}

fun analyze(uri) {
   val bitmap = decodeBitmap(uri)
 .onSuccess{
      apply color filer()
  }.onSuccess {
   save bitmap to file system() 
  }
 }

我在 10 秒内得到 OOM,因为解码、颜色过滤和保存是异步的,例如解码了 100 个位图,但只有 10 个经过颜色过滤,内存被位图溢出,然后我得到了 OOM。

有没有办法在不返回的情况下在 Worker 中运行异步操作? 我将所有流程都重新设计为递归,但似乎不可能在 Worker 中运行递归。也许有一些聪明的暂停方式?

Android 异步 内存不足 android-workmanager coroutineworker

评论

0赞 levi 7/12/2023
什么回报?这是一项任务吗?decodeBitmap
0赞 StayCool 7/12/2023
这是一个异步请求,如果结果成功,则在该位图上运行更多异步代码......

答:

1赞 levi 7/12/2023 #1

您需要创建一个挂起函数,该函数在等待异步请求完成时暂停执行。目前,立即返回,这意味着 2000 个文件正在并行解码。analyzeanalyze

可以使用 suspendCoroutine 来实现此目的。

suspend fun analyze() = suspendCoroutine { continuation ->
      val bitmap = decodeBitmap(uri)
 .onSuccess{
     etc...
  }.onSuccess {
      continuation.resume()
  }
}

评论

0赞 StayCool 7/13/2023
suspendCoroutine 没有成功,因为......要使用它,我必须为 2000 个文件中的每一个启动挂起协程?无论如何,它没有成功。但。
0赞 StayCool 7/13/2023
我用计数器 == 文件大小定义了 CountDownLatch,并将 ref of latch 传递给每个文件(这将在处理结束时 latch.countdown);我计算我通过了多少,有多少不是 countdowned(),如果这个值很大(例如,我启动了 50,但 latch 仍然是 200),所以我等到 latch 为 150 才能继续启动进程。这就像魅力一样,我现在可以控制我想使用多少 RAM(直到我得到 onLowMemory 回调或 OOM)