我需要从图库中获取一些图像,对其进行处理(调整大小,压缩...)并将其保存到特定路径。但是,我需要将呼叫排队,因为较旧的设备将无法同时处理多个图像。
我正在使用Glide,这是用于处理一张图片的代码:
fun processImage(context: Context, sourcePath: String, destinationPath: String, quality: Int, width: Int, height: Int, deleteOriginal: Boolean, callback: ((success: Boolean) -> Unit)) {
val sourceFile = File(sourcePath)
val destinationFile = File(destinationPath)
GlideApp.with(context)
.asBitmap()
.load(sourceFile)
.into(object : SimpleTarget<Bitmap>(width, height) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
try {
destinationFile.writeBytes(ImageUtilities.imageToByteArray(resource, quality, Bitmap.CompressFormat.JPEG, false))
if (deleteOriginal) {
val originalFile = File(sourcePath)
originalFile.delete()
}
callback.invoke(true)
} catch (ex: Exception) {
callback.invoke(false)
}
}
})
}
现在,我通过processNextImage
递归调用自身来手动排队呼叫,直到所有图像都被处理为止:
private fun processImages(sourceImagePaths: List<String>) {
processNextImage(sourceImagePaths, 0)
}
private fun processNextImage(sourceImagePaths: List<String>, index: Int) {
val imagePath = sourceImagePaths[index]
val destination = FileUtilities.generateImagePath()
processImage(this, imagePath, destination, 90, 1000, 1000, false) {
processedImagePaths.add(destination)
if (index + 1 < sourceImagePaths.count())
processImage(sourceImagePaths, index + 1)
else
success()
}
}
但是我不认为这是最好的方法,我尝试研究Kotlin协程,但是我发现的只是队列代码已经被阻塞时的示例,这不适合我的情况,因为Glide已经异步处理了调整大小并在回调中返回结果 onResourceReady
有什么干净的方法可以做到这一点吗?
如官方文档中所述,如果要将基于回调的API转换为基于可挂起的函数的API,可以采用一种简单的模式。我将在这里解释该描述。
您的关键工具是来自标准库的函数suspendCoroutine()
。假设您具有someLongComputation
带有接收Result
对象的回调的函数:
fun someLongComputation(params: Params, callback: (Result) -> Unit)
您可以使用以下简单的代码将其转换为挂起函数:
suspend fun someLongComputation(params: Params): Result =
suspendCoroutine { cont ->
someLongComputation(params) { cont.resume(it) }
}
请注意,传递给原始回调的对象的类型如何仅变为可挂起函数的返回值。
有了它,您可以看到协程的魔力就在您的眼前发生:即使它看起来完全像是阻塞呼叫,但事实并非如此。协程将在后台挂起,并在返回值准备就绪时恢复运行-它将如何恢复完全由您控制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句