Replace RxJava in DownloadQueue (#9016)

* Misc cleanup

- Replace !List.isEmpty with List.isNotEmpty
- Remove redundant case in MoreScreenModel
- Drop no-op StateFlow.catch
  - From lint warning:
> SharedFlow never completes, so this operator typically has not
> effect, it can only catch exceptions from 'onSubscribe' operator

* Convert DownloadQueue queue to MutableStateFlow

Replace delegation to a MutableList with an internal
MutableStateFlow<List>.

In order to avoid modifying every usage of the queue as a list, add
passthrough functions for the currently used list functions. This
should be later refactored, possibly by inlining DownloadQueue
into Downloader.

DownloadQueue.updates was a SharedFlow which updated every time a
change was made to the queue. This is now equivalent to the queue
StateFlow.

Simultaneous assignments to _state.value could cause concurrency
issues. To avoid this, always modify the queue using _state.update.

* Add Download.statusFlow/progressFlow

progressFlow is based on the DownloadQueueScreenModel implementation
rather than the DownloadQueue implementation.

* Reimplement DownloadQueue.statusFlow/progressFlow

Use StateFlow<List<T>>.flatMapLatest() and List<Flow<T>>.merge() to
replicate the effect of PublishSubject.

Use drop(1) to avoid re-emitting the state of each download each time
the merged flow is recreated.

* fixup! Reimplement DownloadQueue.statusFlow/progressFlow
This commit is contained in:
Two-Ai
2023-02-07 22:13:19 -05:00
committed by GitHub
parent 0d8f1c8560
commit bd2cb97179
6 changed files with 92 additions and 116 deletions

View File

@@ -14,7 +14,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
@@ -22,8 +21,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -116,8 +113,7 @@ class DownloadQueueScreenModel(
init {
coroutineScope.launch {
downloadManager.queue.updates
.catch { logcat(LogPriority.ERROR, it) }
downloadManager.queue.state
.map { downloads ->
downloads
.groupBy { it.source }

View File

@@ -95,14 +95,13 @@ private class MoreScreenModel(
coroutineScope.launchIO {
combine(
DownloadService.isRunning,
downloadManager.queue.updates,
downloadManager.queue.state,
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
.collectLatest { (isDownloading, downloadQueueSize) ->
val pendingDownloadExists = downloadQueueSize != 0
_state.value = when {
!pendingDownloadExists -> DownloadQueueState.Stopped
!isDownloading && !pendingDownloadExists -> DownloadQueueState.Paused(0)
!isDownloading && pendingDownloadExists -> DownloadQueueState.Paused(downloadQueueSize)
!isDownloading -> DownloadQueueState.Paused(downloadQueueSize)
else -> DownloadQueueState.Downloading(downloadQueueSize)
}
}