Цепные запросы Kotlin Coroutines - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть массив URL, каждый из которых содержит zip-файл.Я хочу загрузить их и сохранить в папках своего приложения во внутренней памяти.

Вопрос:

Поскольку я не знаю количество URL-адресов, к которым мне нужно получить доступ, что такоелучший способ пойти об этом?Я только начинаю работать с сопрограммами Kotlin.

Это мой метод загрузки с URL

fun downloadResourceArchiveFromUrl(urlString: String, context: Context): Boolean {

    Timber.d("-> Started downloading resource archive.. $urlString")
    lateinit var file: File
    try {
        val url = URL(urlString)

        val urlConn = url.openConnection()
        urlConn.readTimeout = 5000
        urlConn.connectTimeout = 10000

        val inputStream = urlConn.getInputStream()
        val buffInStream = BufferedInputStream(inputStream, 1024 * 5)

        val fileNameFromUrl = urlString.substringAfterLast("/")

        file = File(context.getDir("resources", Context.MODE_PRIVATE) , fileNameFromUrl)

        val outStream = FileOutputStream(file)
        val buff = ByteArray(5 * 1024)

        while (buffInStream.read(buff)  != -1){
            outStream.write(buff, 0, buffInStream.read(buff))
        }

        outStream.flush()
        outStream.close()
        buffInStream.close()

    } catch (e: Exception) {
        e.printStackTrace()
        Timber.d("Download finished with exception: ${e.message} -<")
        return false
    }

    Timber.d("Download finished -<")
    return true
}

Не могли бы вы просто создать цикл и вызвать метод загрузки каждый раз?

        for (i in resources.indices) {
            asyncAwait {
                downloadResourcesFromUrl(resources[i].url, context)
                return@asyncAwait
            }

Кроме того, это хорошая идея сделать это синхронно?Дождаться загрузки каждого файла и переходить к следующему?

1 Ответ

0 голосов
/ 20 ноября 2018

Превратите вашу блокирующую функцию загрузки в приостановленную:

suspend fun downloadResourceArchiveFromUrl(
    urlString: String, context: Context
): Boolean = withContext(Dispatchers.IO) {
   ... your function body
}

Теперь запустите ваш цикл внутри сопрограммы, которую вы launch:

myActivity.launch {
    resources.forEach {
        val success = downloadResourceArchiveFromUrl(it.url, context)
        ... react to success/failure ...
    }
}

Также убедитесь, что правильно реализовали структурированный параллелизм на вашей активности.

...