android - Android 使用 OkHttp 和协程下载多个文件
问题描述
在我的应用程序中,我从 api 获得了一些图像的 url,并且需要Bitmap
从这些 url 创建对象才能在 UI 中显示图像。我看到 android 文档建议使用协程来执行此类异步任务,但我不确定如何正确执行。
将 OkHttp 用于我的 http 客户端,我尝试了以下方法:
GlobalScope.launch {
val gson = Gson();
val parsedRes = gson.fromJson(
response.body?.charStream(),
Array<GoodreadsBook>::class.java
);
// Create the bitmap from the imageUrl
for (i in 0 until parsedRes.size) {
val bitmap =
GlobalScope.async { createBitmapFromUrl(parsedRes[i].best_book.image_url) }
parsedRes[i].best_book.imageBitmap = bitmap.await();
}
searchResults.postValue(parsedRes)
}
response
我从我的 API 中返回的内容在哪里,并且searchResults
是一个LiveData
保存已解析响应的内容。此外,这是我从这些网址获取图像的方式:
suspend fun createBitmapFromUrl(url: String): Bitmap? {
val client = OkHttpClient();
val req = Request.Builder().url(url).build();
val res = client.newCall(req).execute();
return BitmapFactory.decodeStream(res.body?.byteStream())
}
即使每个 fetch 操作都是在一个单独的协程上完成的,它仍然太慢了。有更好的方法吗?我可以使用任何其他 http 客户端,如果有一个优化用于协同程序的客户端,虽然我是 Kotlin 的新手,所以我不知道。
解决方案
首先,所有createBitmapFromUrl(url: String)
事情都是同步的,你必须首先阻止它们阻塞协程线程,你可能想要使用Dispatchers.IO
它,因为回调不是协程中最惯用的东西。
val client = OkHttpClient() // preinitialize the client
suspend fun createBitmapFromUrl(url: String): Bitmap? = withContext(Dispatchers.IO) {
val req = Request.Builder().url(url).build()
val res = client.newCall(req).execute()
BitmapFactory.decodeStream(res.body?.byteStream())
}
现在,当您打电话时,bitmap.await()
您只是在说“嘿,等待延迟bitmap
,一旦完成,就恢复循环以进行下一次迭代”
因此,您可能希望在协程本身中进行分配以阻止它暂停循环,否则为此创建另一个循环。我会选择第一个选项。
scope.launch {
val gson = Gson();
val parsedRes = gson.fromJson(
response.body?.charStream(),
Array<GoodreadsBook>::class.java
);
// Create the bitmap from the imageUrl
for (i in 0 until parsedRes.size) {
launch {
parsedRes[i].best_book.imageBitmap = createBitmapFromUrl(parsedRes[i].best_book.image_url)
}
}
}
推荐阅读
- java - 如何使用绝对文件路径读取 XML 文件
- javascript - 为什么即使页面经过审核,Lighthouse PWA 分数仍为空白
- python - 在 Python 中制作带有类别的频率表
- python - 通过 for 循环遍历列表来构造 f 字符串
- c# - 从 React 前端使用 API POST 到实体框架控制器时总是得到空异常
- reactjs - React 不呈现警报(引导程序)
- python-3.x - 在 elasticsearch 文档中扩展列表字段
- python - 如何在 EC2 实例上从 S3 流式传输 200 万个小文件(2MB 文件)
- solr - 如何让 Solr 在 Red Hat Linux 中重新启动时自动启动?
- git - 从远程存储库中提取特定文件/目录