Lessen the use of GlobalScope launchIO
(#7916)
* Lessen the use of GlobalScope `launchIO` * Wrap some calls with `NonCancellable` context (cherry picked from commit da95ecb6869314f35eb73c6d9245b4e0d127f22d) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
parent
8c92b2fe72
commit
3fc05b03f5
@ -323,7 +323,7 @@ open class BrowseSourcePresenter(
|
||||
if (!new.favorite) {
|
||||
new = new.removeCovers(coverCache)
|
||||
} else {
|
||||
ChapterSettingsHelper.applySettingDefaults(manga)
|
||||
ChapterSettingsHelper.applySettingDefaults(manga.id)
|
||||
|
||||
autoAddTrack(manga)
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ import eu.kanade.tachiyomi.ui.library.setting.display
|
||||
import eu.kanade.tachiyomi.ui.library.setting.sort
|
||||
import eu.kanade.tachiyomi.util.lang.combineLatest
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
||||
@ -726,7 +727,7 @@ class LibraryPresenter(
|
||||
* @param mangas the list of manga.
|
||||
*/
|
||||
fun downloadUnreadChapters(mangas: List<Manga>) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
mangas.forEach { manga ->
|
||||
if (manga.source == MERGED_SOURCE_ID) {
|
||||
val mergedSource = sourceManager.get(MERGED_SOURCE_ID) as MergedSource
|
||||
@ -796,7 +797,7 @@ class LibraryPresenter(
|
||||
* @param mangas the list of manga.
|
||||
*/
|
||||
fun markReadStatus(mangas: List<Manga>, read: Boolean) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
mangas.forEach { manga ->
|
||||
setReadStatus.await(
|
||||
manga = manga,
|
||||
@ -814,7 +815,7 @@ class LibraryPresenter(
|
||||
* @param deleteChapters whether to delete downloaded chapters.
|
||||
*/
|
||||
fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val mangaToDelete = mangaList.distinctBy { it.id }
|
||||
|
||||
if (deleteFromLibrary) {
|
||||
@ -854,7 +855,7 @@ class LibraryPresenter(
|
||||
* @param removeCategories the categories to remove in all mangas.
|
||||
*/
|
||||
fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
mangaList.map { manga ->
|
||||
val categoryIds = getCategories.await(manga.id)
|
||||
.map { it.id }
|
||||
|
@ -63,6 +63,7 @@ import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
||||
import eu.kanade.tachiyomi.util.chapter.getChapterSort
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.toRelativeString
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.preference.asHotFlow
|
||||
@ -799,7 +800,6 @@ class MangaPresenter(
|
||||
/**
|
||||
* Move the given manga to categories.
|
||||
*
|
||||
* @param manga the manga to move.
|
||||
* @param categories the selected categories.
|
||||
*/
|
||||
private fun moveMangaToCategories(categories: List<Category>) {
|
||||
@ -816,7 +816,6 @@ class MangaPresenter(
|
||||
/**
|
||||
* Move the given manga to the category.
|
||||
*
|
||||
* @param manga the manga to move.
|
||||
* @param category the selected category, or null for default category.
|
||||
*/
|
||||
private fun moveMangaToCategory(category: Category?) {
|
||||
@ -1123,7 +1122,7 @@ class MangaPresenter(
|
||||
* @param chapters the list of chapters to delete.
|
||||
*/
|
||||
fun deleteChapters(chapters: List<DomainChapter>) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val chapters2 = chapters.map { it.toDbChapter() }
|
||||
try {
|
||||
updateSuccessState { successState ->
|
||||
@ -1155,10 +1154,10 @@ class MangaPresenter(
|
||||
}
|
||||
|
||||
private fun downloadNewChapters(chapters: List<DomainChapter>) {
|
||||
presenterScope.launchIO {
|
||||
val manga = successState?.manga ?: return@launchIO
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val manga = successState?.manga ?: return@launchNonCancellableIO
|
||||
val categories = getCategories.await(manga.id).map { it.id }
|
||||
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, preferences) || manga.isEhBasedManga()) return@launchIO
|
||||
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, preferences) || manga.isEhBasedManga()) return@launchNonCancellableIO
|
||||
downloadChapters(chapters)
|
||||
}
|
||||
}
|
||||
@ -1175,7 +1174,7 @@ class MangaPresenter(
|
||||
State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD
|
||||
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ
|
||||
}
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@ -1193,7 +1192,7 @@ class MangaPresenter(
|
||||
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED
|
||||
}
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@ -1211,7 +1210,7 @@ class MangaPresenter(
|
||||
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||
}
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@ -1232,7 +1231,7 @@ class MangaPresenter(
|
||||
fun setDisplayMode(mode: Long) {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
setMangaChapterFlags.awaitSetDisplayMode(manga, mode)
|
||||
}
|
||||
}
|
||||
@ -1244,7 +1243,7 @@ class MangaPresenter(
|
||||
fun setSorting(sort: Long) {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort)
|
||||
}
|
||||
}
|
||||
@ -1389,7 +1388,7 @@ class MangaPresenter(
|
||||
|
||||
fun refreshTrackers() {
|
||||
refreshTrackersJob?.cancel()
|
||||
refreshTrackersJob = launchIO {
|
||||
refreshTrackersJob = presenterScope.launchNonCancellableIO {
|
||||
supervisorScope {
|
||||
try {
|
||||
trackList
|
||||
@ -1439,7 +1438,7 @@ class MangaPresenter(
|
||||
val successState = successState ?: return
|
||||
if (item != null) {
|
||||
item.manga_id = successState.manga.id
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
try {
|
||||
val allChapters = successState.chapters.map { it.chapter }
|
||||
val hasReadChapters = allChapters.any { it.read }
|
||||
@ -1481,13 +1480,13 @@ class MangaPresenter(
|
||||
fun unregisterTracking(service: TrackService) {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
deleteTrack.await(manga.id, service.id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRemote(track: Track, service: TrackService) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
try {
|
||||
service.update(track)
|
||||
|
||||
|
@ -54,6 +54,7 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort
|
||||
import eu.kanade.tachiyomi.util.editCover
|
||||
import eu.kanade.tachiyomi.util.lang.byteSize
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.takeBytes
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
@ -275,7 +276,7 @@ class ReaderPresenter(
|
||||
*/
|
||||
fun onSaveInstanceStateNonConfigurationChange() {
|
||||
val currentChapter = getCurrentChapter() ?: return
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
saveChapterProgress(currentChapter)
|
||||
}
|
||||
}
|
||||
@ -615,7 +616,7 @@ class ReaderPresenter(
|
||||
* Called when reader chapter is changed in reader or when activity is paused.
|
||||
*/
|
||||
private fun saveReadingProgress(readerChapter: ReaderChapter) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
saveChapterProgress(readerChapter)
|
||||
saveChapterHistory(readerChapter)
|
||||
}
|
||||
@ -696,7 +697,7 @@ class ReaderPresenter(
|
||||
fun bookmarkCurrentChapter(bookmarked: Boolean) {
|
||||
val chapter = getCurrentChapter()?.chapter ?: return
|
||||
chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
updateChapter.await(
|
||||
ChapterUpdate(
|
||||
id = chapter.id!!.toLong(),
|
||||
@ -831,7 +832,7 @@ class ReaderPresenter(
|
||||
|
||||
// Copy file in background.
|
||||
try {
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val uri = imageSaver.save(
|
||||
image = Image.Page(
|
||||
inputStream = page.stream!!,
|
||||
@ -935,7 +936,7 @@ class ReaderPresenter(
|
||||
val filename = generateFilename(manga, page)
|
||||
|
||||
try {
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
destDir.deleteRecursively()
|
||||
val uri = imageSaver.save(
|
||||
image = Image.Page(
|
||||
@ -991,7 +992,7 @@ class ReaderPresenter(
|
||||
val manga = manga?.toDomainManga() ?: return
|
||||
val stream = page.stream ?: return
|
||||
|
||||
presenterScope.launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
try {
|
||||
manga.editCover(context, stream())
|
||||
withUIContext {
|
||||
@ -1037,7 +1038,7 @@ class ReaderPresenter(
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val context = Injekt.get<Application>()
|
||||
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
getTracks.await(manga.id!!)
|
||||
.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
@ -1081,7 +1082,7 @@ class ReaderPresenter(
|
||||
} ?: return
|
||||
// SY <--
|
||||
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!)
|
||||
}
|
||||
}
|
||||
@ -1091,7 +1092,7 @@ class ReaderPresenter(
|
||||
* are ignored.
|
||||
*/
|
||||
private fun deletePendingChapters() {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
downloadManager.deletePendingChapters()
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.toDateKey
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
@ -223,7 +224,7 @@ class UpdatesPresenter(
|
||||
* @param updatesItem the list of chapters to download.
|
||||
*/
|
||||
fun downloadChapters(updatesItem: List<UpdatesItem>) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
|
||||
for (updates in groupedUpdates) {
|
||||
val mangaId = updates.first().update.mangaId
|
||||
@ -242,7 +243,7 @@ class UpdatesPresenter(
|
||||
* @param updatesItem list of chapters
|
||||
*/
|
||||
fun deleteChapters(updatesItem: List<UpdatesItem>) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
|
||||
val deletedIds = groupedUpdates.flatMap { updates ->
|
||||
val mangaId = updates.first().update.mangaId
|
||||
@ -255,7 +256,7 @@ class UpdatesPresenter(
|
||||
val deletedUpdates = uiModels.filter {
|
||||
it is UpdatesUiModel.Item && deletedIds.contains(it.item.update.chapterId)
|
||||
}
|
||||
if (deletedUpdates.isEmpty()) return@launchIO
|
||||
if (deletedUpdates.isEmpty()) return@launchNonCancellableIO
|
||||
|
||||
// TODO: Don't do this fake status update
|
||||
state.uiModels = uiModels.toMutableList().apply {
|
||||
|
@ -45,7 +45,7 @@ import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.preference.bindTo
|
||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||
@ -102,9 +102,11 @@ class SettingsAdvancedController(
|
||||
summaryRes = R.string.pref_dump_crash_logs_summary
|
||||
|
||||
onClick {
|
||||
viewScope.launchNonCancellableIO {
|
||||
CrashLogUtil(context).dumpLogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*switchPreference {
|
||||
key = Keys.verboseLogging
|
||||
@ -582,7 +584,7 @@ class SettingsAdvancedController(
|
||||
|
||||
private fun clearChapterCache() {
|
||||
val activity = activity ?: return
|
||||
launchIO {
|
||||
viewScope.launchNonCancellableIO {
|
||||
try {
|
||||
val deletedFiles = chapterCache.clear()
|
||||
withUIContext {
|
||||
@ -600,12 +602,13 @@ class SettingsAdvancedController(
|
||||
private fun clearWebViewData() {
|
||||
val activity = activity ?: return
|
||||
try {
|
||||
val webview = WebView(activity)
|
||||
webview.setDefaultSettings()
|
||||
webview.clearCache(true)
|
||||
webview.clearFormData()
|
||||
webview.clearHistory()
|
||||
webview.clearSslPreferences()
|
||||
WebView(activity).run {
|
||||
setDefaultSettings()
|
||||
clearCache(true)
|
||||
clearFormData()
|
||||
clearHistory()
|
||||
clearSslPreferences()
|
||||
}
|
||||
WebStorage.getInstance().deleteAllData()
|
||||
activity.applicationInfo?.dataDir?.let { File("$it/app_webview/").deleteRecursively() }
|
||||
activity.toast(R.string.webview_data_deleted)
|
||||
@ -617,7 +620,7 @@ class SettingsAdvancedController(
|
||||
|
||||
private fun resetViewerFlags() {
|
||||
val activity = activity ?: return
|
||||
launchIO {
|
||||
viewScope.launchNonCancellableIO {
|
||||
val success = mangaRepository.resetViewerFlags()
|
||||
withUIContext {
|
||||
val message = if (success) {
|
||||
|
@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||
@ -22,8 +21,7 @@ class CrashLogUtil(private val context: Context) {
|
||||
setSmallIcon(R.drawable.ic_tachi)
|
||||
}
|
||||
|
||||
fun dumpLogs() {
|
||||
launchIO {
|
||||
suspend fun dumpLogs() {
|
||||
try {
|
||||
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
|
||||
Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}").waitFor()
|
||||
@ -34,7 +32,6 @@ class CrashLogUtil(private val context: Context) {
|
||||
withUIContext { context.toast("Failed to get logs") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getDebugInfo(): String {
|
||||
return """
|
||||
|
@ -24,20 +24,6 @@ object ChapterSettingsHelper {
|
||||
/**
|
||||
* Updates a single manga's Chapter Settings to match what's set in Preferences.
|
||||
*/
|
||||
fun applySettingDefaults(manga: Manga) {
|
||||
launchIO {
|
||||
setMangaChapterFlags.awaitSetAllFlags(
|
||||
mangaId = manga.id,
|
||||
unreadFilter = preferences.filterChapterByRead().toLong(),
|
||||
downloadedFilter = preferences.filterChapterByDownloaded().toLong(),
|
||||
bookmarkedFilter = preferences.filterChapterByBookmarked().toLong(),
|
||||
sortingMode = preferences.sortChapterBySourceOrNumber().toLong(),
|
||||
sortingDirection = preferences.sortChapterByAscendingOrDescending().toLong(),
|
||||
displayMode = preferences.displayChapterByNameOrNumber().toLong(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun applySettingDefaults(mangaId: Long) {
|
||||
setMangaChapterFlags.awaitSetAllFlags(
|
||||
mangaId = mangaId,
|
||||
|
@ -6,6 +6,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@ -48,6 +49,9 @@ fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job =
|
||||
fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job =
|
||||
launch(Dispatchers.IO, block = block)
|
||||
|
||||
fun CoroutineScope.launchNonCancellableIO(block: suspend CoroutineScope.() -> Unit): Job =
|
||||
launchIO { withContext(NonCancellable, block) }
|
||||
|
||||
suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
|
||||
|
||||
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)
|
||||
|
Loading…
x
Reference in New Issue
Block a user