Эх сурвалжийг харах

Introduce coroutines. Fix #1027. Lower notification channels' importance

len 7 жил өмнө
parent
commit
4abd2d709f

+ 11 - 1
app/build.gradle

@@ -218,10 +218,14 @@ dependencies {
     testCompile "org.robolectric:shadows-play-services:$robolectric_version"
 
     compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+    final coroutines_version = '0.19.1'
+    compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
+    compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
 }
 
 buildscript {
-    ext.kotlin_version = '1.1.50'
+    ext.kotlin_version = '1.1.51'
     repositories {
         mavenCentral()
     }
@@ -234,6 +238,12 @@ repositories {
     mavenCentral()
 }
 
+kotlin {
+    experimental {
+        coroutines 'enable'
+    }
+}
+
 // add support for placeholders in resource files
 //https://code.google.com/p/android/issues/detail?id=69224
 def replacePlaceholdersInFile(basePath, fileName, placeholders) {

+ 48 - 50
app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt

@@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.source.model.Page
 import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
 import eu.kanade.tachiyomi.util.*
+import kotlinx.coroutines.experimental.async
 import okhttp3.Response
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
@@ -90,11 +91,10 @@ class Downloader(private val context: Context, private val provider: DownloadPro
     @Volatile private var isRunning: Boolean = false
 
     init {
-        Observable.fromCallable { store.restore() }
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe({ downloads -> queue.addAll(downloads)
-                }, { error -> Timber.e(error) })
+        launchNow {
+            val chapters = async { store.restore() }
+            queue.addAll(chapters.await())
+        }
     }
 
     /**
@@ -217,51 +217,49 @@ class Downloader(private val context: Context, private val provider: DownloadPro
      * @param manga the manga of the chapters to download.
      * @param chapters the list of chapters to download.
      */
-    fun queueChapters(manga: Manga, chapters: List<Chapter>) {
-        val source = sourceManager.get(manga.source) as? HttpSource ?: return
-
-        Observable
-                // Background, long running checks
-                .fromCallable {
-                    val mangaDir = provider.findMangaDir(source, manga)
-
-                    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)
-
-                        // Initialize queue size.
-                        notifier.initialQueueSize = queue.size
-
-                        // 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)
-                        }
-                    }
-                }
+    fun queueChapters(manga: Manga, chapters: List<Chapter>) = launchUI {
+        val source = sourceManager.get(manga.source) as? HttpSource ?: return@launchUI
+
+        // Called in background thread, the operation can be slow with SAF.
+        val chaptersWithoutDir = async {
+            val mangaDir = provider.findMangaDir(source, manga)
+
+            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 }
+        }
+
+        // Runs in main thread (synchronization needed).
+        val chaptersToQueue = chaptersWithoutDir.await()
+                // 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) }
+
+        if (chaptersToQueue.isNotEmpty()) {
+            queue.addAll(chaptersToQueue)
+
+            // Initialize queue size.
+            notifier.initialQueueSize = queue.size
+
+            // 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)
+            }
+
+            // Start downloader if needed
+            DownloadService.start([email protected])
+        }
     }
 
     /**

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt

@@ -43,11 +43,11 @@ object Notifications {
 
         val channels = listOf(
                 NotificationChannel(CHANNEL_COMMON, context.getString(R.string.channel_common),
-                        NotificationManager.IMPORTANCE_DEFAULT),
+                        NotificationManager.IMPORTANCE_LOW),
                 NotificationChannel(CHANNEL_LIBRARY, context.getString(R.string.channel_library),
-                        NotificationManager.IMPORTANCE_DEFAULT),
+                        NotificationManager.IMPORTANCE_LOW),
                 NotificationChannel(CHANNEL_DOWNLOADER, context.getString(R.string.channel_downloader),
-                        NotificationManager.IMPORTANCE_DEFAULT)
+                        NotificationManager.IMPORTANCE_LOW)
         )
         context.notificationManager.createNotificationChannels(channels)
     }

+ 0 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt

@@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.download.DownloadManager
-import eu.kanade.tachiyomi.data.download.DownloadService
 import eu.kanade.tachiyomi.data.download.model.Download
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.source.Source
@@ -35,8 +34,6 @@ class ChaptersPresenter(
         private val downloadManager: DownloadManager = Injekt.get()
 ) : BasePresenter<ChaptersController>() {
 
-    private val context = preferences.context
-
     /**
      * List of chapters of the manga. It's always unfiltered and unsorted.
      */
@@ -246,7 +243,6 @@ class ChaptersPresenter(
      * @param chapters the list of chapters to download.
      */
     fun downloadChapters(chapters: List<ChapterItem>) {
-        DownloadService.start(context)
         downloadManager.downloadChapters(manga, chapters)
     }
 

+ 0 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt

@@ -25,8 +25,6 @@ class RecentChaptersPresenter(
         private val sourceManager: SourceManager = Injekt.get()
 ) : BasePresenter<RecentChaptersController>() {
 
-    private val context = preferences.context
-
     /**
      * List containing chapter and manga information
      */
@@ -207,7 +205,6 @@ class RecentChaptersPresenter(
      */
     fun downloadChapters(items: List<RecentChapterItem>) {
         items.forEach { downloadManager.downloadChapters(it.manga, listOf(it.chapter)) }
-        DownloadService.start(context)
     }
 
     /**

+ 13 - 0
app/src/main/java/eu/kanade/tachiyomi/util/CoroutinesExtensions.kt

@@ -0,0 +1,13 @@
+package eu.kanade.tachiyomi.util
+
+import kotlinx.coroutines.experimental.CoroutineScope
+import kotlinx.coroutines.experimental.CoroutineStart
+import kotlinx.coroutines.experimental.Job
+import kotlinx.coroutines.experimental.android.UI
+import kotlinx.coroutines.experimental.launch
+
+fun launchUI(block: suspend CoroutineScope.() -> Unit): Job =
+        launch(UI, CoroutineStart.DEFAULT, block)
+
+fun launchNow(block: suspend CoroutineScope.() -> Unit): Job =
+        launch(UI, CoroutineStart.UNDISPATCHED, block)