【问题标题】:Coroutine in Fragment causing UIs not to render when navigatingFragment 中的协程导致 UI 在导航时不呈现
【发布时间】:2021-11-03 17:57:40
【问题描述】:

我在片段中使用协程来处理网络请求。但是,当我导航到另一个片段时,下一个片段的 UI 是空白的,并且没有加载任何内容。我正在使用生命周期范围,所以我认为协程会在销毁时被取消/清理,但 UI 返回的唯一方法是注释掉协程。

 lifecycleScope.launch(context = Dispatchers.IO){
        if (pdfResponse != null) {
            try {
                file = getTempPdfFile(pdfResponse)
            } catch (e: Exception) {

            }
    }
}

  private fun getTempPdfFile(body: ResponseBody): File? {
    return try {
        val file = File.createTempFile("myfile", ".pdf")
        var inputStream: InputStream? = null
        var outputStream: OutputStream? = null
        try {
            val fileReader = ByteArray(4096)
            var fileSizeDownloaded: Long = 0
            inputStream = body.byteStream()
            outputStream = FileOutputStream(file)
            while (true) {
                val read: Int = inputStream.read(fileReader)
                if (read == -1) {
                    break
                }
                outputStream.write(fileReader, 0, read)
                fileSizeDownloaded += read.toLong()
            }
            outputStream.flush()
            return file
        } catch (e: IOException) {
            null
        } finally {
            inputStream?.close()
            outputStream?.close()
        }
    } catch (e: IOException) {
        null
    }
}

谁能帮我诊断一下这个问题的原因?

【问题讨论】:

  • 哪个 UI 是空白的?您启动协程的片段还是您导航的片段?
  • 之后导航到的地方
  • 你一开始就不应该这样做。 lifecycleScope 在 Fragment 离开屏幕或屏幕旋转时被取消,然后您将不得不多次冗余地获取文件。使用 ViewModel 获取文件和数据。但是,如果您的 Fragment 实例仍在后台堆栈中,它可能会保持活动状态。至于您的问题,可能与getTempPdfFile 发生的事情有关。
  • 我将代码移到了视图模型中,现在当我正常运行应用程序时它不起作用,但是当我在调试模式下运行它并且应用程序变慢时它可以工作。所以它必须在文件准备好并返回 null 之前完成??

标签: kotlin kotlin-coroutines


【解决方案1】:

我在视图模型中创建了一个挂起函数,如下所示:

 suspend fun createPdfFile()  =
    withContext(Dispatchers.IO) {
        if (getPdfResponse() != null) {
            try {
                file = getPdfResponse()?.let { getTempPdfFile(it) }
            } catch (e: Exception) {
            }
        }
    }

然后在视图中我使用:

lifecycleScope.launch(Dispatchers.Main) {
   createPdfFile()
}

【讨论】:

  • 这解决了你的问题吗?
  • 是的,上述解决方案正在按预期工作
猜你喜欢
  • 2020-09-08
  • 1970-01-01
  • 2021-05-25
  • 2018-08-12
  • 2015-05-29
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
相关资源
最近更新 更多