From 5c662b1ae104df46dec326b102b4179116275a31 Mon Sep 17 00:00:00 2001 From: len Date: Thu, 5 Oct 2017 10:15:02 +0200 Subject: [PATCH] Fix app freezes when queueing many chapters with SAF. Closes #817 --- .../tachiyomi/data/download/Downloader.kt | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index f0aba1a18..64941401d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -91,7 +91,6 @@ class Downloader(private val context: Context, private val provider: DownloadPro init { Observable.fromCallable { store.restore() } - .map { downloads -> downloads.filter { isDownloadAllowed(it) } } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .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 - * must be called in the main thread. + * Creates a download object for every chapter and adds them to the downloads queue. * * @param manga the manga of the 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) { val source = sourceManager.get(manga.source) as? HttpSource ?: return - val chaptersToQueue = chapters - // Avoid downloading chapters with the same name. - .distinctBy { it.name } - // Add chapters to queue from the start. - .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) } + Observable + // Background, long running checks + .fromCallable { + val mangaDir = provider.findMangaDir(source, manga) - // Return if there's nothing to queue. - if (chaptersToQueue.isEmpty()) - return + chapters + // Avoid downloading chapters with the same name. + .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. - notifier.initialQueueSize = queue.size + // Initial multi-thread + notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1 - // Initial multi-thread - notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1 - - if (isRunning) { - // Send the list of downloads to the downloader. - downloadsRelay.call(chaptersToQueue) - } 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 + if (isRunning) { + // Send the list of downloads to the downloader. + downloadsRelay.call(chaptersToQueue) + } else { + // Show initial notification. + notifier.onProgressChange(queue) + } + } + } } /**