我们可以在Android Kotlin的单个Coroutine中下载多个文件吗



大家好,请尽可能多地整理我的查询

我正在开发相册应用程序。在这里,当用户点击特定相册时,我们应该将所有相关图像下载到该特定相册

例如,相册名称为Tree,因此相册具有多个图像url的数组。所以我应该通过url的数组下载该相册中的所有图像

例如:imageArray=arrayOf("url1"、"url2"、"curl3"、"url 4"、……等url(n((

我应该把它们放在循环或递归中,然后我应该在一个接一个完成后下载它们。

我在这里写了一个文件下载的片段,我的疑问是如何继续下载多个文件。

我应该为所有下载的文件使用相同的协同程序,还是为一个文件使用一个协同程序

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"

应该是可能的。

  1. 创建另一个函数,该函数将遍历要下载的文件列表
  2. 使用新函数,使用asynclaunch协程函数-这可以分别对逻辑流、顺序行为或异步行为进行更多控制

例如fun downloadBatch(list: List<Uri>) { GlobalScope.async(Dispatchers.IO) { //logic goes here }}

注意:GlobalScope只是一个简单的例子,不建议在现场制作中使用。

  1. 在迭代器/for循环中,调用一个函数来下载单个文件。此特定函数应在开头附加suspend例如suspend fun downloadFile(uri: Uri)

注意:挂起的函数本身不会使用任何线程逻辑,而是依赖于嵌套在函数Coroutine中。

  1. 继续使用rxJava或尝试LiveData来广播您的文件

最新更新