DownloadWorker: Better handle individual file progress updates
* Don't filter InputStream updates as we are already guarding UI updates against total progress * Update downloadedBytes based on bytesCopied to reflect real progress * Use collect instead of collectLatest to ensure all updates from flow are handled Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -7,7 +7,6 @@ import kotlinx.coroutines.flow.flow
|
|||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
|
||||||
import kotlin.concurrent.fixedRateTimer
|
import kotlin.concurrent.fixedRateTimer
|
||||||
|
|
||||||
fun InputStream.copyTo(out: OutputStream, streamSize: Long): Flow<DownloadInfo> {
|
fun InputStream.copyTo(out: OutputStream, streamSize: Long): Flow<DownloadInfo> {
|
||||||
@@ -29,9 +28,9 @@ fun InputStream.copyTo(out: OutputStream, streamSize: Long): Flow<DownloadInfo>
|
|||||||
out.write(buffer, 0, bytes)
|
out.write(buffer, 0, bytes)
|
||||||
bytesCopied += bytes
|
bytesCopied += bytes
|
||||||
// Emit stream progress in percentage
|
// Emit stream progress in percentage
|
||||||
emit(DownloadInfo((bytesCopied * 100 / streamSize).toInt(), bytesCopied, speed))
|
emit(DownloadInfo((bytesCopied * 100 / streamSize).toInt(), bytes.toLong(), speed))
|
||||||
bytes = read(buffer)
|
bytes = read(buffer)
|
||||||
}
|
}
|
||||||
timer.cancel()
|
timer.cancel()
|
||||||
}.flowOn(Dispatchers.IO).distinctUntilChangedBy { it.progress }
|
}.flowOn(Dispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ import dagger.assisted.AssistedInject
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.NonCancellable
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
@@ -264,7 +263,7 @@ class DownloadWorker @AssistedInject constructor(
|
|||||||
|
|
||||||
connection.inputStream.use { input ->
|
connection.inputStream.use { input ->
|
||||||
FileOutputStream(request.file, !isNewFile).use {
|
FileOutputStream(request.file, !isNewFile).use {
|
||||||
input.copyTo(it, request.size).collectLatest { p -> onProgress(p) }
|
input.copyTo(it, request.size).collect { p -> onProgress(p) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,17 +280,15 @@ class DownloadWorker @AssistedInject constructor(
|
|||||||
|
|
||||||
private suspend fun onProgress(downloadInfo: DownloadInfo) {
|
private suspend fun onProgress(downloadInfo: DownloadInfo) {
|
||||||
if (!isStopped && !download.isFinished) {
|
if (!isStopped && !download.isFinished) {
|
||||||
val progress = ((downloadedBytes + downloadInfo.bytesCopied) * 100 / totalBytes).toInt()
|
downloadedBytes += downloadInfo.bytesCopied
|
||||||
val bytesRemaining = totalBytes - (downloadedBytes + downloadInfo.bytesCopied)
|
|
||||||
|
val progress = (downloadedBytes * 100 / totalBytes).toInt()
|
||||||
|
val bytesRemaining = totalBytes - downloadedBytes
|
||||||
val speed = if (downloadInfo.speed == 0L) 1 else downloadInfo.speed
|
val speed = if (downloadInfo.speed == 0L) 1 else downloadInfo.speed
|
||||||
|
|
||||||
// Individual file progress can be negligible in contrast to total progress
|
// Individual file progress can be negligible in contrast to total progress
|
||||||
// Only notify the UI if progress is greater or speed has changed to avoid being rate-limited by Android
|
// Only notify the UI if progress is greater or speed has changed to avoid being rate-limited by Android
|
||||||
if (progress > totalProgress || speed != download.speed) {
|
if (progress > totalProgress || speed != download.speed) {
|
||||||
if (downloadInfo.progress == 100) {
|
|
||||||
downloadedBytes += downloadInfo.bytesCopied
|
|
||||||
}
|
|
||||||
|
|
||||||
download.apply {
|
download.apply {
|
||||||
this.progress = progress
|
this.progress = progress
|
||||||
this.speed = downloadInfo.speed
|
this.speed = downloadInfo.speed
|
||||||
|
|||||||
Reference in New Issue
Block a user