【发布时间】:2021-04-07 13:46:24
【问题描述】:
您好所有开发者,请尽可能多地整理我的查询。
我正在开发相册应用程序。在这里,当用户单击特定相册时,我们应该将所有相关图像下载到该特定相册。
例如专辑名称是树,所以专辑有多个图像 url 的数组。所以我应该通过 url 的数组下载该专辑中的所有图片
例如:imageArray = arrayOf("url1","url2","url3","url4",....等 url(n))
我应该将它们放入 for 循环或递归中,然后我应该在完成时将它们下载到 (n) 个 url。
我在这里为一个文件下载编写了 sn-p 我的疑问是如何继续下载多个文件。
我应该对所有文件下载使用相同的协程还是一个一个文件一个一个协程
CoroutineScope(Dispatchers.IO).launch {
**//here itself i can run for loop or else any other robust/proper way to do this requirement.**
ktor.downloadFile(outputStream, url).collect {
withContext(Dispatchers.Main) {
when (it) {
is DownloadResult.Success -> {
**//on success of one file download should i call recursively to download one more file by this method - private fun downloadFile(context: Context, url: String, file: Uri)**
viewFile(file)
}
下面是下载单个文件的代码
private fun downloadFile(context: Context, url: String, file: Uri) {
val ktor = HttpClient(Android)
contentResolver.openOutputStream(file)?.let { outputStream ->
CoroutineScope(Dispatchers.IO).launch {
ktor.downloadFile(outputStream, url).collect {
withContext(Dispatchers.Main) {
when (it) {
is DownloadResult.Success -> {
viewFile(file)
}
is DownloadResult.Error -> {
}
is DownloadResult.Progress -> {
txtProgress.text = "${it.progress}"
}
}
}
}
}
}
}
suspend fun HttpClient.downloadFile(file: OutputStream, url: String): Flow<DownloadResult> {
return flow {
try {
val response = call {
url(url)
method = HttpMethod.Get
}.response
val data = ByteArray(response.contentLength()!!.toInt())
var offset = 0
do {
val currentRead = response.content.readAvailable(data, offset, data.size)
offset += currentRead
val progress = (offset * 100f / data.size).roundToInt()
emit(DownloadResult.Progress(progress))
} while (currentRead > 0)
response.close()
if (response.status.isSuccess()) {
withContext(Dispatchers.IO) {
file.write(data)
}
emit(DownloadResult.Success)
} else {
emit(DownloadResult.Error("File not downloaded"))
}
} catch (e: TimeoutCancellationException) {
emit(DownloadResult.Error("Connection timed out", e))
} catch (t: Throwable) {
emit(DownloadResult.Error("Failed to connect"))
}
}
}
sealed class DownloadResult {
object Success : DownloadResult()
data class Error(val message: String, val cause: Exception? = null) : DownloadResult()
data class Progress(val progress: Int): DownloadResult()
}
我用过的 Gradle 文件
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
implementation "io.ktor:ktor-client-android:1.2.5"
【问题讨论】:
-
方法调用已弃用。并阻止响应,直到它被完全接收。您将无法获得实时进度
标签: android kotlin kotlin-coroutines android-download-manager ktor