android retrofit download progress

前端 未结 3 659
傲寒
傲寒 2020-12-08 16:50

I\'m new to retrofit. I\'ve searched but didn\'t found a simple answer. I want to know how can I show progress of download in Notification bar or at least show a progress di

3条回答
  •  生来不讨喜
    2020-12-08 17:44

    Here is my variant with Kotlin's coroutines

    1. Specify API interface. We need @Streaming annotation to say Retrofit that we want to handle response body manually. Otherwise retrofit will try write your file straight into RAM
    interface Api {
    
        @Streaming
        @GET("get-zip-ulr/{id}")
        fun getZip(@Path("id") id: Int): Call
    }
    
    1. Create DataSource which will control downloading process
    class FilesDataSource(private val parentFolder: File, private val api: Api) {
    
        suspend fun downloadZip(id: Int, processCallback: (Long, Long) -> Unit): File {
            val response = api.getZip(id).awaitResponse()// returns the response, but it's content will be later
            val body = response.body()
            if (response.isSuccessful && body != null) {
                val file = File(parentFolder, "$id")
                body.byteStream().use { inputStream ->
                    FileOutputStream(file).use { outputStream ->
                        val data = ByteArray(8192)
                        var read: Int
                        var progress = 0L
                        val fileSize = body.contentLength()
                        while (inputStream.read(data).also { read = it } != -1) {
                            outputStream.write(data, 0, read)
                            progress += read
                            publishProgress(processCallback, progress, fileSize)
                        }
                        publishProgress(processCallback, fileSize, fileSize)
                    }
                }
                return file
            } else {
                throw HttpException(response)
            }
        }
    
        private suspend fun publishProgress(
            callback: (Long, Long) -> Unit,
            progress: Long, //bytes
            fileSize: Long  //bytes
        ) {
            withContext(Dispatchers.Main) { // invoke callback in UI thtread
                callback(progress, fileSize)
            }
        }
    }
    

    Now you can execute downloadZip() method in your ViewModel or Presenter and give it callback which will be linked to some ProgerssBar. After download completion you will receive downloaded file.

提交回复
热议问题