繁体   English   中英

在 Kotlin 协程中无法读取 Okio 源代码

[英]Okio source cannot be read inside a Kotlin Coroutine

我正在尝试使用此实现从 Okio 源生成位图

val file = /* ... */
    
Okio.source(file).use {
    CoroutineScope(Dispatchers.IO).launch {
        Okio.buffer(source).use { bufferedSource ->

            val bitmap = BitmapFactory.decodeStream(bufferedSource.inputStream())

            withContext(Dispatchers.Main) {
                view.setImageBitmap(bitmap)
            }
        }
    }   
}

事情是,生成的位图为null ,我得到以下日志

W/System.err: java.io.IOException: Stream Closed
W/System.err:     at java.io.FileInputStream.read(FileInputStream.java:313)
W/System.err:     at okio.InputStreamSource.read(Okio.kt:102)
W/System.err:     at okio.RealBufferedSource$inputStream$1.read(RealBufferedSource.kt:438)
W/System.err:     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
W/System.err:     at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:790)
W/System.err:     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:765)
W/System.err:     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:806)
W/System.err:     at **************************************$1.invokeSuspend(ImageRenderer.kt:32)
W/System.err:     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
W/System.err:     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
W/System.err:     at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
W/System.err:     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
W/System.err:     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
W/System.err:     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
D/skia: ---- read threw an exception
D/skia: --- Failed to create image decoder with message 'unimplemented'

在协程之外(即在主线程中)执行相同的操作会导致位图正确解码。 感谢您帮助找出为什么在协程中未正确读取源代码。

您的代码段有一些问题:

  1. 您正在创建一个与某物(活动、片段、视图等)的生命周期无关的范围。 永远不要随意创建一个范围,并且总是启动一个与其他生命周期相关的范围(即,在某处调用cancel() )。
  2. 您正在调用线程(主线程)上打开文件。 Okio.source(File)打开涉及可能阻塞的文件 I/O 的文件。 在 IO 调度程序上打开协程内的文件。
  3. 您正在缓冲一个use块。 通过调用use { launch { } }您正在关闭文件,然后启动的协程可以运行以读取文件。 一起打开和缓冲文件源。
  4. 在等待协程在主线程上运行时,您将保持缓冲源处于活动状态。 在将协程转移到主调度程序之前,允许文件的use块完成。

最终代码应如下所示:

val file = /* ... */
    
scope.launch(Dispatchers.IO) {
  val bitmap = Okio.buffer(Okio.source(file)).use { bufferedSource ->
    BitmapFactory.decodeStream(bufferedSource.inputStream())
  }

  withContext(Dispatchers.Main) {
    view.setImageBitmap(bitmap)
  }  
}

此外,请考虑升级您的 Okio 版本,该版本现在用 Kotlin 编写并通过扩展函数工作:

val file = /* ... */
    
scope.launch(Dispatchers.IO) {
  val bitmap = file.source().buffer().use { bufferedSource ->
    BitmapFactory.decodeStream(bufferedSource.inputStream())
  }

  withContext(Dispatchers.Main) {
    view.setImageBitmap(bitmap)
  }  
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM