Lessen the use of GlobalScope launchIO (#7916)

* Lessen the use of GlobalScope `launchIO`

* Wrap some calls with `NonCancellable` context
This commit is contained in:
AntsyLich 2022-09-02 21:50:44 +06:00 committed by GitHub
parent 774a87a42a
commit da95ecb686
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 59 additions and 67 deletions

View File

@ -244,7 +244,7 @@ open class BrowseSourcePresenter(
if (!new.favorite) { if (!new.favorite) {
new = new.removeCovers(coverCache) new = new.removeCovers(coverCache)
} else { } else {
ChapterSettingsHelper.applySettingDefaults(manga) ChapterSettingsHelper.applySettingDefaults(manga.id)
autoAddTrack(manga) autoAddTrack(manga)
} }

View File

@ -49,6 +49,7 @@ import eu.kanade.tachiyomi.ui.library.setting.display
import eu.kanade.tachiyomi.ui.library.setting.sort import eu.kanade.tachiyomi.ui.library.setting.sort
import eu.kanade.tachiyomi.util.lang.combineLatest import eu.kanade.tachiyomi.util.lang.combineLatest
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -511,7 +512,7 @@ class LibraryPresenter(
* @param mangas the list of manga. * @param mangas the list of manga.
*/ */
fun downloadUnreadChapters(mangas: List<Manga>) { fun downloadUnreadChapters(mangas: List<Manga>) {
launchIO { presenterScope.launchNonCancellableIO {
mangas.forEach { manga -> mangas.forEach { manga ->
val chapters = getChapterByMangaId.await(manga.id) val chapters = getChapterByMangaId.await(manga.id)
.filter { !it.read } .filter { !it.read }
@ -528,7 +529,7 @@ class LibraryPresenter(
* @param mangas the list of manga. * @param mangas the list of manga.
*/ */
fun markReadStatus(mangas: List<Manga>, read: Boolean) { fun markReadStatus(mangas: List<Manga>, read: Boolean) {
launchIO { presenterScope.launchNonCancellableIO {
mangas.forEach { manga -> mangas.forEach { manga ->
setReadStatus.await( setReadStatus.await(
manga = manga, manga = manga,
@ -546,7 +547,7 @@ class LibraryPresenter(
* @param deleteChapters whether to delete downloaded chapters. * @param deleteChapters whether to delete downloaded chapters.
*/ */
fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) { fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
launchIO { presenterScope.launchNonCancellableIO {
val mangaToDelete = mangaList.distinctBy { it.id } val mangaToDelete = mangaList.distinctBy { it.id }
if (deleteFromLibrary) { if (deleteFromLibrary) {
@ -579,7 +580,7 @@ class LibraryPresenter(
* @param removeCategories the categories to remove in all mangas. * @param removeCategories the categories to remove in all mangas.
*/ */
fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) { fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
mangaList.map { manga -> mangaList.map { manga ->
val categoryIds = getCategories.await(manga.id) val categoryIds = getCategories.await(manga.id)
.map { it.id } .map { it.id }

View File

@ -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.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.lang.launchIO 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.toRelativeString
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.preference.asHotFlow
@ -396,7 +397,6 @@ class MangaPresenter(
/** /**
* Move the given manga to categories. * Move the given manga to categories.
* *
* @param manga the manga to move.
* @param categories the selected categories. * @param categories the selected categories.
*/ */
private fun moveMangaToCategories(categories: List<Category>) { private fun moveMangaToCategories(categories: List<Category>) {
@ -413,7 +413,6 @@ class MangaPresenter(
/** /**
* Move the given manga to the category. * Move the given manga to the category.
* *
* @param manga the manga to move.
* @param category the selected category, or null for default category. * @param category the selected category, or null for default category.
*/ */
private fun moveMangaToCategory(category: Category?) { private fun moveMangaToCategory(category: Category?) {
@ -643,7 +642,7 @@ class MangaPresenter(
* @param chapters the list of chapters to delete. * @param chapters the list of chapters to delete.
*/ */
fun deleteChapters(chapters: List<DomainChapter>) { fun deleteChapters(chapters: List<DomainChapter>) {
launchIO { presenterScope.launchNonCancellableIO {
val chapters2 = chapters.map { it.toDbChapter() } val chapters2 = chapters.map { it.toDbChapter() }
try { try {
updateSuccessState { successState -> updateSuccessState { successState ->
@ -675,10 +674,10 @@ class MangaPresenter(
} }
private fun downloadNewChapters(chapters: List<DomainChapter>) { private fun downloadNewChapters(chapters: List<DomainChapter>) {
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
val manga = successState?.manga ?: return@launchIO val manga = successState?.manga ?: return@launchNonCancellableIO
val categories = getCategories.await(manga.id).map { it.id } 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) downloadChapters(chapters)
} }
} }
@ -695,7 +694,7 @@ class MangaPresenter(
State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ
} }
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
} }
} }
@ -713,7 +712,7 @@ class MangaPresenter(
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED
} }
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag)
} }
} }
@ -731,7 +730,7 @@ class MangaPresenter(
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED
} }
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag)
} }
} }
@ -743,7 +742,7 @@ class MangaPresenter(
fun setDisplayMode(mode: Long) { fun setDisplayMode(mode: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
setMangaChapterFlags.awaitSetDisplayMode(manga, mode) setMangaChapterFlags.awaitSetDisplayMode(manga, mode)
} }
} }
@ -755,7 +754,7 @@ class MangaPresenter(
fun setSorting(sort: Long) { fun setSorting(sort: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort)
} }
} }
@ -870,7 +869,7 @@ class MangaPresenter(
fun refreshTrackers() { fun refreshTrackers() {
refreshTrackersJob?.cancel() refreshTrackersJob?.cancel()
refreshTrackersJob = launchIO { refreshTrackersJob = presenterScope.launchNonCancellableIO {
supervisorScope { supervisorScope {
try { try {
trackList trackList
@ -918,7 +917,7 @@ class MangaPresenter(
val successState = successState ?: return val successState = successState ?: return
if (item != null) { if (item != null) {
item.manga_id = successState.manga.id item.manga_id = successState.manga.id
launchIO { presenterScope.launchNonCancellableIO {
try { try {
val allChapters = successState.chapters.map { it.chapter } val allChapters = successState.chapters.map { it.chapter }
val hasReadChapters = allChapters.any { it.read } val hasReadChapters = allChapters.any { it.read }
@ -959,13 +958,13 @@ class MangaPresenter(
fun unregisterTracking(service: TrackService) { fun unregisterTracking(service: TrackService) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
deleteTrack.await(manga.id, service.id) deleteTrack.await(manga.id, service.id)
} }
} }
private fun updateRemote(track: Track, service: TrackService) { private fun updateRemote(track: Track, service: TrackService) {
launchIO { presenterScope.launchNonCancellableIO {
try { try {
service.update(track) service.update(track)

View File

@ -47,6 +47,7 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.editCover
import eu.kanade.tachiyomi.util.lang.byteSize import eu.kanade.tachiyomi.util.lang.byteSize
import eu.kanade.tachiyomi.util.lang.launchIO 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.takeBytes
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
@ -231,7 +232,7 @@ class ReaderPresenter(
*/ */
fun onSaveInstanceStateNonConfigurationChange() { fun onSaveInstanceStateNonConfigurationChange() {
val currentChapter = getCurrentChapter() ?: return val currentChapter = getCurrentChapter() ?: return
launchIO { presenterScope.launchNonCancellableIO {
saveChapterProgress(currentChapter) saveChapterProgress(currentChapter)
} }
} }
@ -518,7 +519,7 @@ class ReaderPresenter(
* Called when reader chapter is changed in reader or when activity is paused. * Called when reader chapter is changed in reader or when activity is paused.
*/ */
private fun saveReadingProgress(readerChapter: ReaderChapter) { private fun saveReadingProgress(readerChapter: ReaderChapter) {
launchIO { presenterScope.launchNonCancellableIO {
saveChapterProgress(readerChapter) saveChapterProgress(readerChapter)
saveChapterHistory(readerChapter) saveChapterHistory(readerChapter)
} }
@ -599,7 +600,7 @@ class ReaderPresenter(
fun bookmarkCurrentChapter(bookmarked: Boolean) { fun bookmarkCurrentChapter(bookmarked: Boolean) {
val chapter = getCurrentChapter()?.chapter ?: return val chapter = getCurrentChapter()?.chapter ?: return
chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
launchIO { presenterScope.launchNonCancellableIO {
updateChapter.await( updateChapter.await(
ChapterUpdate( ChapterUpdate(
id = chapter.id!!.toLong(), id = chapter.id!!.toLong(),
@ -712,7 +713,7 @@ class ReaderPresenter(
// Copy file in background. // Copy file in background.
try { try {
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
val uri = imageSaver.save( val uri = imageSaver.save(
image = Image.Page( image = Image.Page(
inputStream = page.stream!!, inputStream = page.stream!!,
@ -748,7 +749,7 @@ class ReaderPresenter(
val filename = generateFilename(manga, page) val filename = generateFilename(manga, page)
try { try {
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
destDir.deleteRecursively() destDir.deleteRecursively()
val uri = imageSaver.save( val uri = imageSaver.save(
image = Image.Page( image = Image.Page(
@ -774,7 +775,7 @@ class ReaderPresenter(
val manga = manga?.toDomainManga() ?: return val manga = manga?.toDomainManga() ?: return
val stream = page.stream ?: return val stream = page.stream ?: return
presenterScope.launchIO { presenterScope.launchNonCancellableIO {
try { try {
manga.editCover(context, stream()) manga.editCover(context, stream())
withUIContext { withUIContext {
@ -820,7 +821,7 @@ class ReaderPresenter(
val trackManager = Injekt.get<TrackManager>() val trackManager = Injekt.get<TrackManager>()
val context = Injekt.get<Application>() val context = Injekt.get<Application>()
launchIO { presenterScope.launchNonCancellableIO {
getTracks.await(manga.id!!) getTracks.await(manga.id!!)
.mapNotNull { track -> .mapNotNull { track ->
val service = trackManager.getService(track.syncId) val service = trackManager.getService(track.syncId)
@ -858,7 +859,7 @@ class ReaderPresenter(
if (!chapter.chapter.read) return if (!chapter.chapter.read) return
val manga = manga ?: return val manga = manga ?: return
launchIO { presenterScope.launchNonCancellableIO {
downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!) downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!)
} }
} }
@ -868,7 +869,7 @@ class ReaderPresenter(
* are ignored. * are ignored.
*/ */
private fun deletePendingChapters() { private fun deletePendingChapters() {
launchIO { presenterScope.launchNonCancellableIO {
downloadManager.deletePendingChapters() downloadManager.deletePendingChapters()
} }
} }

View File

@ -22,6 +22,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO 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.toDateKey
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
@ -221,7 +222,7 @@ class UpdatesPresenter(
* @param updatesItem the list of chapters to download. * @param updatesItem the list of chapters to download.
*/ */
fun downloadChapters(updatesItem: List<UpdatesItem>) { fun downloadChapters(updatesItem: List<UpdatesItem>) {
launchIO { presenterScope.launchNonCancellableIO {
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
for (updates in groupedUpdates) { for (updates in groupedUpdates) {
val mangaId = updates.first().update.mangaId val mangaId = updates.first().update.mangaId
@ -240,7 +241,7 @@ class UpdatesPresenter(
* @param updatesItem list of chapters * @param updatesItem list of chapters
*/ */
fun deleteChapters(updatesItem: List<UpdatesItem>) { fun deleteChapters(updatesItem: List<UpdatesItem>) {
launchIO { presenterScope.launchNonCancellableIO {
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
val deletedIds = groupedUpdates.flatMap { updates -> val deletedIds = groupedUpdates.flatMap { updates ->
val mangaId = updates.first().update.mangaId val mangaId = updates.first().update.mangaId
@ -253,7 +254,7 @@ class UpdatesPresenter(
val deletedUpdates = uiModels.filter { val deletedUpdates = uiModels.filter {
it is UpdatesUiModel.Item && deletedIds.contains(it.item.update.chapterId) 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 // TODO: Don't do this fake status update
state.uiModels = uiModels.toMutableList().apply { state.uiModels = uiModels.toMutableList().apply {

View File

@ -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.base.controller.pushController
import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController
import eu.kanade.tachiyomi.util.CrashLogUtil 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.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.bindTo import eu.kanade.tachiyomi.util.preference.bindTo
import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.defaultValue
@ -89,7 +89,9 @@ class SettingsAdvancedController(
summaryRes = R.string.pref_dump_crash_logs_summary summaryRes = R.string.pref_dump_crash_logs_summary
onClick { onClick {
CrashLogUtil(context).dumpLogs() viewScope.launchNonCancellableIO {
CrashLogUtil(context).dumpLogs()
}
} }
} }
@ -340,7 +342,7 @@ class SettingsAdvancedController(
private fun clearChapterCache() { private fun clearChapterCache() {
val activity = activity ?: return val activity = activity ?: return
launchIO { viewScope.launchNonCancellableIO {
try { try {
val deletedFiles = chapterCache.clear() val deletedFiles = chapterCache.clear()
withUIContext { withUIContext {
@ -358,12 +360,13 @@ class SettingsAdvancedController(
private fun clearWebViewData() { private fun clearWebViewData() {
val activity = activity ?: return val activity = activity ?: return
try { try {
val webview = WebView(activity) WebView(activity).run {
webview.setDefaultSettings() setDefaultSettings()
webview.clearCache(true) clearCache(true)
webview.clearFormData() clearFormData()
webview.clearHistory() clearHistory()
webview.clearSslPreferences() clearSslPreferences()
}
WebStorage.getInstance().deleteAllData() WebStorage.getInstance().deleteAllData()
activity.applicationInfo?.dataDir?.let { File("$it/app_webview/").deleteRecursively() } activity.applicationInfo?.dataDir?.let { File("$it/app_webview/").deleteRecursively() }
activity.toast(R.string.webview_data_deleted) activity.toast(R.string.webview_data_deleted)
@ -375,7 +378,7 @@ class SettingsAdvancedController(
private fun resetViewerFlags() { private fun resetViewerFlags() {
val activity = activity ?: return val activity = activity ?: return
launchIO { viewScope.launchNonCancellableIO {
val success = mangaRepository.resetViewerFlags() val success = mangaRepository.resetViewerFlags()
withUIContext { withUIContext {
val message = if (success) { val message = if (success) {

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications 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.lang.withUIContext
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.createFileInCacheDir import eu.kanade.tachiyomi.util.system.createFileInCacheDir
@ -21,17 +20,15 @@ class CrashLogUtil(private val context: Context) {
setSmallIcon(R.drawable.ic_tachi) setSmallIcon(R.drawable.ic_tachi)
} }
fun dumpLogs() { suspend fun dumpLogs() {
launchIO { try {
try { val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt") Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}").waitFor()
Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}").waitFor() file.appendText(getDebugInfo())
file.appendText(getDebugInfo())
showNotification(file.getUriCompat(context)) showNotification(file.getUriCompat(context))
} catch (e: Throwable) { } catch (e: Throwable) {
withUIContext { context.toast("Failed to get logs") } withUIContext { context.toast("Failed to get logs") }
}
} }
} }

View File

@ -24,20 +24,6 @@ object ChapterSettingsHelper {
/** /**
* Updates a single manga's Chapter Settings to match what's set in Preferences. * 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) { suspend fun applySettingDefaults(mangaId: Long) {
setMangaChapterFlags.awaitSetAllFlags( setMangaChapterFlags.awaitSetAllFlags(
mangaId = mangaId, mangaId = mangaId,

View File

@ -6,6 +6,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -48,6 +49,9 @@ fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job =
fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job = fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job =
launch(Dispatchers.IO, block = block) 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> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block) suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)