gpt4 book ai didi

android - 在 CoroutineScope 中下载多个图像

转载 作者:行者123 更新时间:2023-12-04 23:56:07 24 4
gpt4 key购买 nike

我需要下载多张图片,并在所有下载完成后(在主线程之外),在 Activity 中执行其他操作。

我目前使用Glide下载如下:

ImageDownloader.kt

class ImageDownloader {
fun downloadPack(context: Context, path: String, pack: PackModel) {
for (image: ImageModel in pack.images) {
Glide.with(context)
.asBitmap()
.load(image.imageFileUrl)
.listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
return false
}

override fun onResourceReady(bitmap: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
saveImage(path, pack.id, image.imageFileName, bitmap!!)
return true
}
}).submit()
}
}

private fun saveImage(path: String, id: String, fileName: String, bitmap: Bitmap) {
val dir = File(path + id)
if (!dir.exists()) dir.mkdirs()
val file = File(dir, fileName)
val out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 75, out)
out.flush()
out.close()
// to check the download progress for each image in logcat
println("done: $fileName")
}
}

在 Activity 中,我在 CoroutineScope 中调用此方法,如下所示:

PackActivity.kt

class PackActivity: AppCompatActivity() {
private lateinit var bind: ActivityPackBinding
private lateinit var path: String
private lateinit var pack: PackModel
// other basic codes

override fun onCreate(savedInstanceState: Bundle?) {
// other basic codes
path = "$filesDir/images_asset/"
pack = intent.getParcelableExtra(PACK_DATA)!!

bind.buttonDownload.setOnClickListener {
downloadPack()
}
}

private fun downloadPack() {
CoroutineScope(Dispatchers.IO).launch {
val async = async {
ImageDownloader().downloadPack(applicationContext, path, pack)
}
val result = async.await()
withContext(Dispatchers.Main) {
result.apply {
println("finished")
// other things todo
}
}
}
}
}

在下载 PackActivity.kt 中的所有图像后,我试图继续执行其他操作,但结果是,使用 println("finished") 并检查 logcat,代码开始甚至在第一次下载开始之前...

一些信息:

PackModel 和 ImageModel 是我的数据类,其中 PackModel 具有每个包的 ID 和 ImageModel 列表,后者又具有 ImageFileName 和 ImageFileUrl。所有数据均来自网络请求。

我希望将图像保存在文件夹 data/data/AppPackageName/files/images_asset/PackID/... 通过我所做的测试,我无法使用 DownloadManager 将图像定向到应用程序的这个内部文件夹,这就是我使用 Glide 的原因。

最佳答案

关键的第一步是使用 suspendCancellableCoroutine 将异步 Glide 请求调整为 suspend fun。方法如下:

private suspend fun downloadBitmap(
context: Context,
image: ImageModel
) = suspendCancellableCoroutine<Bitmap> { cont ->
Glide.with(context)
.asBitmap()
.load(image.imageFileUrl)
.listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException, model: Any?,
target: Target<Bitmap>?, isFirstResource: Boolean
): Boolean {
cont.resumeWith(Result.failure(e))
return false
}

override fun onResourceReady(
bitmap: Bitmap, model: Any?, target: Target<Bitmap>?,
dataSource: DataSource?, isFirstResource: Boolean
): Boolean {
cont.resumeWith(Result.success(bitmap))
return false
}
}).submit()
}

完成后,现在您可以轻松地进行并发下载并等待所有下载:

class ImageDownloader {
suspend fun downloadPack(context: Context, path: String, pack: PackModel) {
coroutineScope {
for (image: ImageModel in pack.images) {
launch {
val bitmap = downloadBitmap(context, image)
saveImage(path, pack.id, image.imageFileName, bitmap)
}
}
}
}


private suspend fun saveImage(
path: String, id: String, imageFileName: String, bitmap: Bitmap
) {
withContext(IO) {
// your code
}
}
}

仔细观察我在上面使用的调度程序:对除 saveImage 之外的所有内容都使用 Main 调度程序,这是唯一包含实际阻塞代码的地方。

最后,要使用一切,这就是您所需要的:

private fun downloadPack() {
GlobalScope.launch {
ImageDownloader().downloadPack(applicationContext, path, pack)
println("finished")
// other things todo
}
}

同样,Main 调度程序中的所有内容,因为阻塞代码已安全地集中在 IO 调度程序中。

我在上面使用 GlobalScope 是因为不了解您的更大上下文,但这可能是个坏主意。编写 CoroutineScope(IO).launch 有所有相同的问题,而且还要分配更多的对象。

如果用户离开应用程序,或者如果他们反复离开和返回,触发越来越多的后台下载,请三思您的下载会发生什么。在上面的代码中,我没有在 suspendCancellableCoroutine 中处理取消,因为我对 Glide 不是很熟悉。您应该添加一个 cont.onCancellation 处理程序才能正确。

关于android - 在 CoroutineScope 中下载多个图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66721355/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com