Fix app freezes when queueing many chapters with SAF. Closes #817

This commit is contained in:
len 2017-10-05 10:15:02 +02:00
parent f648940388
commit 5c662b1ae1

View File

@ -91,7 +91,6 @@ class Downloader(private val context: Context, private val provider: DownloadPro
init { init {
Observable.fromCallable { store.restore() } Observable.fromCallable { store.restore() }
.map { downloads -> downloads.filter { isDownloadAllowed(it) } }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ downloads -> queue.addAll(downloads) .subscribe({ downloads -> queue.addAll(downloads)
@ -213,8 +212,7 @@ class Downloader(private val context: Context, private val provider: DownloadPro
} }
/** /**
* Creates a download object for every chapter and adds them to the downloads queue. This method * Creates a download object for every chapter and adds them to the downloads queue.
* must be called in the main thread.
* *
* @param manga the manga of the chapters to download. * @param manga the manga of the chapters to download.
* @param chapters the list of chapters to download. * @param chapters the list of chapters to download.
@ -222,52 +220,48 @@ class Downloader(private val context: Context, private val provider: DownloadPro
fun queueChapters(manga: Manga, chapters: List<Chapter>) { fun queueChapters(manga: Manga, chapters: List<Chapter>) {
val source = sourceManager.get(manga.source) as? HttpSource ?: return val source = sourceManager.get(manga.source) as? HttpSource ?: return
val chaptersToQueue = chapters Observable
// Avoid downloading chapters with the same name. // Background, long running checks
.distinctBy { it.name } .fromCallable {
// Add chapters to queue from the start. val mangaDir = provider.findMangaDir(source, manga)
.sortedByDescending { it.source_order }
// Create a downloader for each one.
.map { Download(source, manga, it) }
// Filter out those already queued or downloaded.
.filter { isDownloadAllowed(it) }
// Return if there's nothing to queue. chapters
if (chaptersToQueue.isEmpty()) // Avoid downloading chapters with the same name.
return .distinctBy { it.name }
// Filter out those already downloaded.
.filter { mangaDir?.findFile(provider.getChapterDirName(it)) == null }
// Add chapters to queue from the start.
.sortedByDescending { it.source_order }
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
// Main thread, quick checks
.map { chaptersToQueue ->
chaptersToQueue
// Filter out those already enqueued.
.filter { chapter -> queue.none { it.chapter.id == chapter.id } }
// Create a download for each one.
.map { Download(source, manga, it) }
}
.subscribe { chaptersToQueue ->
if (chaptersToQueue.isNotEmpty()) {
queue.addAll(chaptersToQueue)
queue.addAll(chaptersToQueue) // Initialize queue size.
notifier.initialQueueSize = queue.size
// Initialize queue size. // Initial multi-thread
notifier.initialQueueSize = queue.size notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1
// Initial multi-thread if (isRunning) {
notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1 // Send the list of downloads to the downloader.
downloadsRelay.call(chaptersToQueue)
if (isRunning) { } else {
// Send the list of downloads to the downloader. // Show initial notification.
downloadsRelay.call(chaptersToQueue) notifier.onProgressChange(queue)
} else { }
// Show initial notification. }
notifier.onProgressChange(queue) }
}
}
/**
* Returns true if the given download can be queued and downloaded.
*
* @param download the download to be checked.
*/
private fun isDownloadAllowed(download: Download): Boolean {
// If the chapter is already queued, don't add it again
if (queue.any { it.chapter.id == download.chapter.id })
return false
val dir = provider.findChapterDir(download.source, download.manga, download.chapter)
if (dir != null && dir.exists())
return false
return true
} }
/** /**