mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Lessen the use of GlobalScope launchIO (#7916)
				
					
				
			* Lessen the use of GlobalScope `launchIO` * Wrap some calls with `NonCancellable` context
This commit is contained in:
		| @@ -244,7 +244,7 @@ open class BrowseSourcePresenter( | ||||
|             if (!new.favorite) { | ||||
|                 new = new.removeCovers(coverCache) | ||||
|             } else { | ||||
|                 ChapterSettingsHelper.applySettingDefaults(manga) | ||||
|                 ChapterSettingsHelper.applySettingDefaults(manga.id) | ||||
|  | ||||
|                 autoAddTrack(manga) | ||||
|             } | ||||
|   | ||||
| @@ -49,6 +49,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.removeCovers | ||||
| import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State | ||||
| import kotlinx.coroutines.Job | ||||
| @@ -511,7 +512,7 @@ class LibraryPresenter( | ||||
|      * @param mangas the list of manga. | ||||
|      */ | ||||
|     fun downloadUnreadChapters(mangas: List<Manga>) { | ||||
|         launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             mangas.forEach { manga -> | ||||
|                 val chapters = getChapterByMangaId.await(manga.id) | ||||
|                     .filter { !it.read } | ||||
| @@ -528,7 +529,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, | ||||
| @@ -546,7 +547,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) { | ||||
| @@ -579,7 +580,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 } | ||||
|   | ||||
| @@ -42,6 +42,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 | ||||
| @@ -396,7 +397,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>) { | ||||
| @@ -413,7 +413,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?) { | ||||
| @@ -643,7 +642,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 -> | ||||
| @@ -675,10 +674,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)) return@launchIO | ||||
|             if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, preferences)) return@launchNonCancellableIO | ||||
|             downloadChapters(chapters) | ||||
|         } | ||||
|     } | ||||
| @@ -695,7 +694,7 @@ class MangaPresenter( | ||||
|             State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD | ||||
|             State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ | ||||
|         } | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) | ||||
|         } | ||||
|     } | ||||
| @@ -713,7 +712,7 @@ class MangaPresenter( | ||||
|             State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED | ||||
|         } | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) | ||||
|         } | ||||
|     } | ||||
| @@ -731,7 +730,7 @@ class MangaPresenter( | ||||
|             State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED | ||||
|         } | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) | ||||
|         } | ||||
|     } | ||||
| @@ -743,7 +742,7 @@ class MangaPresenter( | ||||
|     fun setDisplayMode(mode: Long) { | ||||
|         val manga = successState?.manga ?: return | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             setMangaChapterFlags.awaitSetDisplayMode(manga, mode) | ||||
|         } | ||||
|     } | ||||
| @@ -755,7 +754,7 @@ class MangaPresenter( | ||||
|     fun setSorting(sort: Long) { | ||||
|         val manga = successState?.manga ?: return | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) | ||||
|         } | ||||
|     } | ||||
| @@ -870,7 +869,7 @@ class MangaPresenter( | ||||
|  | ||||
|     fun refreshTrackers() { | ||||
|         refreshTrackersJob?.cancel() | ||||
|         refreshTrackersJob = launchIO { | ||||
|         refreshTrackersJob = presenterScope.launchNonCancellableIO { | ||||
|             supervisorScope { | ||||
|                 try { | ||||
|                     trackList | ||||
| @@ -918,7 +917,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 } | ||||
| @@ -959,13 +958,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) | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,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 | ||||
| @@ -231,7 +232,7 @@ class ReaderPresenter( | ||||
|      */ | ||||
|     fun onSaveInstanceStateNonConfigurationChange() { | ||||
|         val currentChapter = getCurrentChapter() ?: return | ||||
|         launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             saveChapterProgress(currentChapter) | ||||
|         } | ||||
|     } | ||||
| @@ -518,7 +519,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) | ||||
|         } | ||||
| @@ -599,7 +600,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(), | ||||
| @@ -712,7 +713,7 @@ class ReaderPresenter( | ||||
|  | ||||
|         // Copy file in background. | ||||
|         try { | ||||
|             presenterScope.launchIO { | ||||
|             presenterScope.launchNonCancellableIO { | ||||
|                 val uri = imageSaver.save( | ||||
|                     image = Image.Page( | ||||
|                         inputStream = page.stream!!, | ||||
| @@ -748,7 +749,7 @@ class ReaderPresenter( | ||||
|         val filename = generateFilename(manga, page) | ||||
|  | ||||
|         try { | ||||
|             presenterScope.launchIO { | ||||
|             presenterScope.launchNonCancellableIO { | ||||
|                 destDir.deleteRecursively() | ||||
|                 val uri = imageSaver.save( | ||||
|                     image = Image.Page( | ||||
| @@ -774,7 +775,7 @@ class ReaderPresenter( | ||||
|         val manga = manga?.toDomainManga() ?: return | ||||
|         val stream = page.stream ?: return | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             try { | ||||
|                 manga.editCover(context, stream()) | ||||
|                 withUIContext { | ||||
| @@ -820,7 +821,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) | ||||
| @@ -858,7 +859,7 @@ class ReaderPresenter( | ||||
|         if (!chapter.chapter.read) return | ||||
|         val manga = manga ?: return | ||||
|  | ||||
|         launchIO { | ||||
|         presenterScope.launchNonCancellableIO { | ||||
|             downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!) | ||||
|         } | ||||
|     } | ||||
| @@ -868,7 +869,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 | ||||
| @@ -221,7 +222,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 | ||||
| @@ -240,7 +241,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 | ||||
| @@ -253,7 +254,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 { | ||||
|   | ||||
| @@ -32,7 +32,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 | ||||
| @@ -89,7 +89,9 @@ class SettingsAdvancedController( | ||||
|             summaryRes = R.string.pref_dump_crash_logs_summary | ||||
|  | ||||
|             onClick { | ||||
|                 CrashLogUtil(context).dumpLogs() | ||||
|                 viewScope.launchNonCancellableIO { | ||||
|                     CrashLogUtil(context).dumpLogs() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -340,7 +342,7 @@ class SettingsAdvancedController( | ||||
|  | ||||
|     private fun clearChapterCache() { | ||||
|         val activity = activity ?: return | ||||
|         launchIO { | ||||
|         viewScope.launchNonCancellableIO { | ||||
|             try { | ||||
|                 val deletedFiles = chapterCache.clear() | ||||
|                 withUIContext { | ||||
| @@ -358,12 +360,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) | ||||
| @@ -375,7 +378,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 | ||||
| @@ -21,17 +20,15 @@ class CrashLogUtil(private val context: Context) { | ||||
|         setSmallIcon(R.drawable.ic_tachi) | ||||
|     } | ||||
|  | ||||
|     fun dumpLogs() { | ||||
|         launchIO { | ||||
|             try { | ||||
|                 val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt") | ||||
|                 Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}").waitFor() | ||||
|                 file.appendText(getDebugInfo()) | ||||
|     suspend fun dumpLogs() { | ||||
|         try { | ||||
|             val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt") | ||||
|             Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}").waitFor() | ||||
|             file.appendText(getDebugInfo()) | ||||
|  | ||||
|                 showNotification(file.getUriCompat(context)) | ||||
|             } catch (e: Throwable) { | ||||
|                 withUIContext { context.toast("Failed to get logs") } | ||||
|             } | ||||
|             showNotification(file.getUriCompat(context)) | ||||
|         } catch (e: Throwable) { | ||||
|             withUIContext { context.toast("Failed to get logs") } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user