Use app scoped CoroutineScope (#3403)
This commit is contained in:
@@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
@@ -53,6 +54,7 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
@@ -63,17 +65,16 @@ import kotlin.time.Duration.Companion.seconds
|
||||
*/
|
||||
class DownloadCache(
|
||||
private val context: Context,
|
||||
private val scope: CoroutineScope,
|
||||
private val provider: DownloadProvider = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
private val storageManager: StorageManager = Injekt.get(),
|
||||
) {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
private val _changes: Channel<Unit> = Channel(Channel.UNLIMITED)
|
||||
val changes = _changes.receiveAsFlow()
|
||||
.onStart { emit(Unit) }
|
||||
.flowOn(Dispatchers.IO)
|
||||
.shareIn(scope, SharingStarted.Lazily, 1)
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ class DownloadCache(
|
||||
|
||||
init {
|
||||
// Attempt to read cache file
|
||||
scope.launch {
|
||||
scope.launchIO {
|
||||
rootDownloadsDirMutex.withLock {
|
||||
try {
|
||||
if (diskCacheFile.exists()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.drop
|
||||
@@ -35,6 +36,7 @@ import uy.kohesive.injekt.api.get
|
||||
*/
|
||||
class DownloadManager(
|
||||
private val context: Context,
|
||||
private val scope: CoroutineScope,
|
||||
private val provider: DownloadProvider = Injekt.get(),
|
||||
private val cache: DownloadCache = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
@@ -45,7 +47,7 @@ class DownloadManager(
|
||||
/**
|
||||
* Downloader whose only task is to download chapters.
|
||||
*/
|
||||
private val downloader = Downloader(context, provider, cache)
|
||||
private val downloader = Downloader(context, provider, cache, scope)
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = downloader.isRunning
|
||||
@@ -221,7 +223,7 @@ class DownloadManager(
|
||||
* @param source the source of the chapters.
|
||||
*/
|
||||
fun deleteChapters(chapters: List<Chapter>, manga: Manga, source: Source) {
|
||||
launchIO {
|
||||
scope.launchIO {
|
||||
val filteredChapters = getChaptersToDelete(chapters, manga)
|
||||
if (filteredChapters.isEmpty()) {
|
||||
return@launchIO
|
||||
@@ -248,7 +250,7 @@ class DownloadManager(
|
||||
* @param removeQueued whether to also remove queued downloads.
|
||||
*/
|
||||
fun deleteManga(manga: Manga, source: Source, removeQueued: Boolean = true) {
|
||||
launchIO {
|
||||
scope.launchIO {
|
||||
if (removeQueued) {
|
||||
downloader.removeFromQueue(manga)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ import okhttp3.Response
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.storage.extension
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.core.common.util.lang.launchNow
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
@@ -71,6 +70,7 @@ class Downloader(
|
||||
private val context: Context,
|
||||
private val provider: DownloadProvider,
|
||||
private val cache: DownloadCache,
|
||||
private val scope: CoroutineScope,
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val chapterCache: ChapterCache = Injekt.get(),
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
@@ -95,7 +95,6 @@ class Downloader(
|
||||
*/
|
||||
private val notifier by lazy { DownloadNotifier(context) }
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private var downloaderJob: Job? = null
|
||||
|
||||
/**
|
||||
@@ -111,7 +110,7 @@ class Downloader(
|
||||
var isPaused: Boolean = false
|
||||
|
||||
init {
|
||||
launchNow {
|
||||
scope.launch {
|
||||
val chapters = async { store.restore() }
|
||||
addAllToQueue(chapters.await())
|
||||
}
|
||||
@@ -190,7 +189,7 @@ class Downloader(
|
||||
private fun launchDownloaderJob() {
|
||||
if (isRunning) return
|
||||
|
||||
downloaderJob = scope.launch {
|
||||
downloaderJob = scope.launchIO {
|
||||
val activeDownloadsFlow = combine(
|
||||
queueState,
|
||||
downloadPreferences.parallelSourceLimit.changes(),
|
||||
|
||||
@@ -28,6 +28,8 @@ import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.getBitmapOrNull
|
||||
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.notify
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.core.common.i18n.pluralStringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
@@ -44,7 +46,7 @@ import java.text.NumberFormat
|
||||
|
||||
class LibraryUpdateNotifier(
|
||||
private val context: Context,
|
||||
|
||||
private val scope: CoroutineScope = Injekt.get(),
|
||||
private val securityPreferences: SecurityPreferences = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
) {
|
||||
@@ -209,7 +211,7 @@ class LibraryUpdateNotifier(
|
||||
|
||||
// Per-manga notification
|
||||
if (!securityPreferences.hideNotificationContent.get()) {
|
||||
launchUI {
|
||||
scope.launch {
|
||||
context.notify(
|
||||
updates.map { (manga, chapters) ->
|
||||
NotificationManagerCompat.NotificationWithIdAndTag(
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
@@ -17,6 +19,10 @@ import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
@@ -32,6 +38,8 @@ import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||
|
||||
/**
|
||||
@@ -45,6 +53,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
private val getChapter: GetChapter by injectLazy()
|
||||
private val updateChapter: UpdateChapter by injectLazy()
|
||||
private val downloadManager: DownloadManager by injectLazy()
|
||||
private val scope: CoroutineScope by injectLazy()
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when (intent.action) {
|
||||
@@ -197,7 +206,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val downloadPreferences: DownloadPreferences = Injekt.get()
|
||||
val sourceManager: SourceManager = Injekt.get()
|
||||
|
||||
launchIO {
|
||||
async(scope, Dispatchers.IO) {
|
||||
val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
|
||||
.map {
|
||||
val chapter = it.copy(read = true)
|
||||
@@ -223,13 +232,27 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* @param mangaId id of manga
|
||||
*/
|
||||
private fun downloadChapters(chapterUrls: Array<String>, mangaId: Long) {
|
||||
launchIO {
|
||||
val manga = getManga.await(mangaId) ?: return@launchIO
|
||||
async(scope, Dispatchers.IO) {
|
||||
val manga = getManga.await(mangaId) ?: return@async
|
||||
val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
|
||||
downloadManager.downloadChapters(manga, chapters)
|
||||
}
|
||||
}
|
||||
|
||||
private fun BroadcastReceiver.async(
|
||||
scope: CoroutineScope,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
block: suspend CoroutineScope.() -> Unit,
|
||||
) {
|
||||
val result = goAsync()
|
||||
try {
|
||||
scope.launch(context, start, block)
|
||||
} finally {
|
||||
result.finish()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "NotificationReceiver"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user