使用主线程而非后台线程运行协程

3

我有一个应用程序,用户从文件浏览器选择一个pdf文件,然后我需要将该pdf文件转换为base64格式。

以下是我的代码,用于将pdf转换为base64:

private fun convertImageFileToBase64(imageFile: File?): String {
        return FileInputStream(imageFile).use { inputStream ->
            ByteArrayOutputStream().use { outputStream ->
                Base64OutputStream(outputStream, Base64.DEFAULT).use { base64FilterStream ->
                    inputStream.copyTo(base64FilterStream)
                    base64FilterStream.flush()
                    outputStream.toString()
                }
            }
        }
    }

因此,在获取PDF文件的onActivityResult中,我编写了以下代码:

launch {
    withContext(Dispatchers.IO) {
        generatedBase64 = convertImageFileToBase64(file)
    }

    //upload generatedBase64 to server
}

但是,如果 PDF 文件很大,代码将在主线程上运行而不是在后台线程上运行,我的 UI 会冻结一段时间。我也尝试过 AsyncTask 并尝试在 doInBackground 方法中执行转换,但我遇到了相同的问题。


1
AsyncTask 在我看来大多数都是垃圾。一个普通的旧线程就可以工作。例如 Thread t = new Thread(...... - CmosBattery
1
@CmosBattery 但是协程有什么问题呢?为什么在将PDF转换为Base64时我的UI会冻结? - user10241787
1
你所说的“冻结”是指什么?是指像onclicklisteners这样的一些UI代码在运行时不执行吗?还是只是“//将生成的base64上传到服务器”部分? - kamyar haqqani
1
你启动协程时使用的上下文是什么?我猜你可能像这样使用:Dispatchers.Main + Job()。如果是这样,在你放置注释“上传生成的Base64到服务器”的地方,它将在主线程上运行。你需要像调用 convertImageFileToBase64 函数一样切换上下文。 - Sergio
@kamyarhaqqani onclicklisteners不起作用。 - user10241787
@Sergey 是的,我正在使用 Dispatchers.Main + Job()。 - user10241787
1个回答

4
如果您像这样使用Dispatchers.Main + Job()作为上下文来启动协程,那么在您有“将生成的Base64上传到服务器”注释的位置将在主线程上运行。 您需要像调用convertImageFileToBase64函数一样切换上下文,以便上传generatedBase64到服务器,即使用withContext(Dispatchers.IO)
launch {
    withContext(Dispatchers.IO) {
        generatedBase64 = convertImageFileToBase64(file)
        //upload generatedBase64 to server here
    }
    // do UI stuff here, e.g. show some message, set text to TextView etc.
}

会尝试一下并让您知道。 - user10241787

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接