Будет ли этот код утекать ресурсы при отмене сопрограммы? - PullRequest
0 голосов
/ 09 апреля 2020

Будет ли следующий код пропускать ресурсы при отмене сопрограммы Kotlin?

Общие сведения: код вложен во ViewModel! Метод retrievePDFDocument будет запущен в событии onStart фрагмента.

fun retrievePDFDocument() {
    job = viewModelScope.launch {
        withContext(Dispatchers.IO) {
            downloadFile(assetPath.value!!)
        }
    }
}

А здесь функция приостановки:

private fun downloadFile(strPdfUrl: String): File? {
    var inputStream: InputStream? = null
    val lenghtOfFile: Int  //lenghtOfFile is used for calculating download progress

    //this is where the file will be seen after the download
    var fileOut: FileOutputStream? = null
    var localPDFFile: File? = null

    if(strPdfUrl.isBlank())
        return localPDFFile

    try {
        val pdfUrl = URL(strPdfUrl)
        val urlConnection = pdfUrl.openConnection() as HttpURLConnection
        if (urlConnection.responseCode == 200) {
            //file input is from the url
            inputStream = BufferedInputStream(urlConnection.inputStream)
            lenghtOfFile = urlConnection.contentLength
            localPDFFile = File(localPdfDirectory, pdfFileName.value!!)
            fileOut = FileOutputStream(localPDFFile)

            //here’s the download code
            val buffer = ByteArray(1024)
            var total: Long = 0

            while (true) {
                // If coroutine is cancelled
                // a CancellationException will be thrown here
                // Do not more work then necesarry
                coroutineContext.ensureActive()

                val length = inputStream.read(buffer)
                if (length <= 0) break
                total += length.toLong()
                _currProgress.postValue( (total * 100 / lenghtOfFile).toInt()  )
                fileOut.write(buffer, 0, length)
            }
        }

    } catch (e: IOException) {
        Log.e("PdfViewerViewModel - downloadFile Error: ${e.message}")
        localPdfFile?.delete() // remove partially downloaded file
        localPDFFile = null
    } catch (e1: CancellationException) {
        Log.e("PdfViewerViewModel - downloadFile CancellationException: ${e1.message}")
        localPdfFile?.delete() // remove partially downloaded file
        localPdfFile = null
    finally {
        try {
            inputStream?.close()
            fileOut?.apply {
                flush()
                close()
            }
        } catch (e1: IOException) { //do nothing here }
    }
    return localPDFFile
}

С уважением, Франк

@ Обновление 10.04 .2020 Реализация с coroutineContext.ensureActive () и перехват исключения

...