diff --git a/app/src/main/java/io/legado/app/api/controller/BookController.kt b/app/src/main/java/io/legado/app/api/controller/BookController.kt index d9bd46ac9..9ba9eb25d 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookController.kt @@ -110,9 +110,9 @@ object BookController { ?: return returnData.setErrorMsg("未找到对应书源,请换源") val toc = runBlocking { if (book.tocUrl.isBlank()) { - WebBook.getBookInfoAwait(this, bookSource, book) + WebBook.getBookInfoAwait(bookSource, book) } - WebBook.getChapterListAwait(this, bookSource, book).getOrThrow() + WebBook.getChapterListAwait(bookSource, book).getOrThrow() } appDb.bookChapterDao.delByBook(book.bookUrl) appDb.bookChapterDao.insert(*toc.toTypedArray()) diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt index c926cdc5f..e9d371a2d 100644 --- a/app/src/main/java/io/legado/app/help/BookHelp.kt +++ b/app/src/main/java/io/legado/app/help/BookHelp.kt @@ -68,14 +68,13 @@ object BookHelp { } suspend fun saveContent( - scope: CoroutineScope, bookSource: BookSource, book: Book, bookChapter: BookChapter, content: String ) { saveText(book, bookChapter, content) - saveImages(scope, bookSource, book, bookChapter, content) + saveImages(bookSource, book, bookChapter, content) postEvent(EventBus.SAVE_CONTENT, bookChapter) } @@ -95,7 +94,6 @@ object BookHelp { } private suspend fun saveImages( - scope: CoroutineScope, bookSource: BookSource, book: Book, bookChapter: BookChapter, @@ -107,8 +105,10 @@ object BookHelp { if (matcher.find()) { matcher.group(1)?.let { src -> val mSrc = NetworkUtils.getAbsoluteURL(bookChapter.url, src) - awaitList.add(scope.async { - saveImage(bookSource, book, mSrc) + awaitList.add(coroutineScope { + async { + saveImage(bookSource, book, mSrc) + } }) } } diff --git a/app/src/main/java/io/legado/app/model/CacheBook.kt b/app/src/main/java/io/legado/app/model/CacheBook.kt index 6a286faf8..2861b485b 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -179,7 +179,7 @@ object CacheBook { val chapterCount = appDb.bookChapterDao.getChapterCount(book.bookUrl) if (chapterCount == 0) { runBlocking { - WebBook.getChapterListAwait(this, bookSource, book) + WebBook.getChapterListAwait(bookSource, book) .onFailure { AppLog.put("缓存书籍没有目录且加载目录失败\n${it.localizedMessage}", it) appCtx.toastOnUi("缓存书籍没有目录且加载目录失败\n${it.localizedMessage}") diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index 408806cf3..1be49d990 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -700,7 +700,7 @@ class AnalyzeRule( book.putVariable(entry.key, entry.value) } } - WebBook.getBookInfoAwait(this, bookSource, book, false) + WebBook.getBookInfoAwait(bookSource, book, false) } } } @@ -714,7 +714,7 @@ class AnalyzeRule( if (bookSource == null || book == null) return runBlocking { withTimeout(1800000) { - WebBook.getBookInfoAwait(this, bookSource, book) + WebBook.getBookInfoAwait(bookSource, book) } } } @@ -728,7 +728,7 @@ class AnalyzeRule( if (bookSource == null || book == null) return runBlocking { withTimeout(1800000) { - WebBook.getBookInfoAwait(this, bookSource, book) + WebBook.getBookInfoAwait(bookSource, book) } } } diff --git a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt index 289884c3f..8a5570f0b 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt @@ -13,12 +13,12 @@ import io.legado.app.model.Debug import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.utils.isTrue -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.async import kotlinx.coroutines.ensureActive import kotlinx.coroutines.withContext import splitties.init.appCtx +import kotlin.coroutines.coroutineContext /** * 获取目录 @@ -26,7 +26,6 @@ import splitties.init.appCtx object BookChapterList { suspend fun analyzeChapterList( - scope: CoroutineScope, bookSource: BookSource, book: Book, baseUrl: String, @@ -52,7 +51,7 @@ object BookChapterList { } var chapterData = analyzeChapterList( - scope, book, baseUrl, redirectUrl, body, + book, baseUrl, redirectUrl, body, tocRule, listRule, bookSource, log = true ) chapterList.addAll(chapterData.first) @@ -69,7 +68,7 @@ object BookChapterList { headerMapF = bookSource.getHeaderMap() ).getStrResponseAwait().body?.let { nextBody -> chapterData = analyzeChapterList( - scope, book, nextUrl, nextUrl, + book, nextUrl, nextUrl, nextBody, tocRule, listRule, bookSource ) nextUrl = chapterData.second.firstOrNull() ?: "" @@ -92,7 +91,7 @@ object BookChapterList { ) val res = analyzeUrl.getStrResponseAwait() analyzeChapterList( - this, book, urlStr, res.url, + book, urlStr, res.url, res.body!!, tocRule, listRule, bookSource, false ).first } @@ -110,14 +109,14 @@ object BookChapterList { if (!reverse) { chapterList.reverse() } - scope.ensureActive() + coroutineContext.ensureActive() val lh = LinkedHashSet(chapterList) val list = ArrayList(lh) if (!book.getReverseToc()) { list.reverse() } Debug.log(book.origin, "◇目录总数:${list.size}") - scope.ensureActive() + coroutineContext.ensureActive() list.forEachIndexed { index, bookChapter -> bookChapter.index = index } @@ -131,12 +130,11 @@ object BookChapterList { } book.lastCheckTime = System.currentTimeMillis() book.totalChapterNum = list.size - scope.ensureActive() + coroutineContext.ensureActive() return list } - private fun analyzeChapterList( - scope: CoroutineScope, + private suspend fun analyzeChapterList( book: Book, baseUrl: String, redirectUrl: String, @@ -173,7 +171,7 @@ object BookChapterList { log ) } - scope.ensureActive() + coroutineContext.ensureActive() if (elements.isNotEmpty()) { Debug.log(bookSource.bookSourceUrl, "┌解析目录列表", log) val nameRule = analyzeRule.splitSourceRule(tocRule.chapterName) @@ -183,7 +181,7 @@ object BookChapterList { val upTimeRule = analyzeRule.splitSourceRule(tocRule.updateTime) val isVolumeRule = analyzeRule.splitSourceRule(tocRule.isVolume) elements.forEachIndexed { index, item -> - scope.ensureActive() + coroutineContext.ensureActive() analyzeRule.setContent(item) val bookChapter = BookChapter(bookUrl = book.bookUrl, baseUrl = redirectUrl) analyzeRule.chapter = bookChapter diff --git a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt index dbcc6ff5b..5347442a3 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt @@ -14,12 +14,12 @@ import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.utils.HtmlFormatter import io.legado.app.utils.NetworkUtils -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.async import kotlinx.coroutines.ensureActive import kotlinx.coroutines.withContext import splitties.init.appCtx +import kotlin.coroutines.coroutineContext /** * 获取正文 @@ -28,7 +28,6 @@ object BookContent { @Throws(Exception::class) suspend fun analyzeContent( - scope: CoroutineScope, bookSource: BookSource, book: Book, bookChapter: BookChapter, @@ -55,7 +54,7 @@ object BookContent { val analyzeRule = AnalyzeRule(book, bookSource).setContent(body, baseUrl) analyzeRule.setRedirectUrl(redirectUrl) analyzeRule.nextChapterUrl = mNextChapterUrl - scope.ensureActive() + coroutineContext.ensureActive() var contentData = analyzeContent( book, baseUrl, redirectUrl, body, contentRule, bookChapter, bookSource, mNextChapterUrl ) @@ -68,7 +67,7 @@ object BookContent { == NetworkUtils.getAbsoluteURL(redirectUrl, mNextChapterUrl) ) break nextUrlList.add(nextUrl) - scope.ensureActive() + coroutineContext.ensureActive() val res = AnalyzeUrl( mUrl = nextUrl, source = bookSource, @@ -106,7 +105,7 @@ object BookContent { } } asyncArray.forEach { coroutine -> - scope.ensureActive() + coroutineContext.ensureActive() content.append("\n").append(coroutine.await()) } } @@ -124,7 +123,7 @@ object BookContent { throw ContentEmptyException("内容为空") } if (needSave) { - BookHelp.saveContent(scope, bookSource, book, bookChapter, contentStr) + BookHelp.saveContent(bookSource, book, bookChapter, contentStr) } return contentStr } diff --git a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt index 9595b1079..d7b87d8b3 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt @@ -13,9 +13,9 @@ import io.legado.app.utils.DebugLog import io.legado.app.utils.HtmlFormatter import io.legado.app.utils.NetworkUtils import io.legado.app.utils.StringUtils.wordCountFormat -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ensureActive import splitties.init.appCtx +import kotlin.coroutines.coroutineContext /** @@ -24,8 +24,7 @@ import splitties.init.appCtx object BookInfo { @Throws(Exception::class) - fun analyzeBookInfo( - scope: CoroutineScope, + suspend fun analyzeBookInfo( bookSource: BookSource, book: Book, baseUrl: String, @@ -41,11 +40,10 @@ object BookInfo { val analyzeRule = AnalyzeRule(book, bookSource) analyzeRule.setContent(body).setBaseUrl(baseUrl) analyzeRule.setRedirectUrl(redirectUrl) - analyzeBookInfo(scope, book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName) + analyzeBookInfo(book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName) } - fun analyzeBookInfo( - scope: CoroutineScope, + suspend fun analyzeBookInfo( book: Book, body: String, analyzeRule: AnalyzeRule, @@ -57,13 +55,13 @@ object BookInfo { val infoRule = bookSource.getBookInfoRule() infoRule.init?.let { if (it.isNotBlank()) { - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "≡执行详情页初始化规则") analyzeRule.setContent(analyzeRule.getElement(it)) } } val mCanReName = canReName && !infoRule.canReName.isNullOrBlank() - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取书名") BookHelp.formatBookName(analyzeRule.getString(infoRule.name)).let { if (it.isNotEmpty() && (mCanReName || book.name.isEmpty())) { @@ -71,7 +69,7 @@ object BookInfo { } Debug.log(bookSource.bookSourceUrl, "└${it}") } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取作者") BookHelp.formatBookAuthor(analyzeRule.getString(infoRule.author)).let { if (it.isNotEmpty() && (mCanReName || book.author.isEmpty())) { @@ -79,7 +77,7 @@ object BookInfo { } Debug.log(bookSource.bookSourceUrl, "└${it}") } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取分类") try { analyzeRule.getStringList(infoRule.kind) @@ -92,7 +90,7 @@ object BookInfo { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}") DebugLog.e("获取分类出错", e) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取字数") try { wordCountFormat(analyzeRule.getString(infoRule.wordCount)).let { @@ -103,7 +101,7 @@ object BookInfo { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}") DebugLog.e("获取字数出错", e) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取最新章节") try { analyzeRule.getString(infoRule.lastChapter).let { @@ -114,7 +112,7 @@ object BookInfo { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}") DebugLog.e("获取最新章节出错", e) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取简介") try { HtmlFormatter.format(analyzeRule.getString(infoRule.intro)).let { @@ -125,7 +123,7 @@ object BookInfo { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}") DebugLog.e("获取简介出错", e) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取封面链接") try { analyzeRule.getString(infoRule.coverUrl).let { @@ -140,7 +138,7 @@ object BookInfo { DebugLog.e("获取封面出错", e) } if (book.type != BookType.file) { - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取目录链接") book.tocUrl = analyzeRule.getString(infoRule.tocUrl, isUrl = true) if (book.tocUrl.isEmpty()) book.tocUrl = baseUrl @@ -149,7 +147,7 @@ object BookInfo { } Debug.log(bookSource.bookSourceUrl, "└${book.tocUrl}") } else { - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取文件下载链接") book.downloadUrls = analyzeRule.getStringList(infoRule.downloadUrls, isUrl = true) if (book.downloadUrls == null) { diff --git a/app/src/main/java/io/legado/app/model/webBook/BookList.kt b/app/src/main/java/io/legado/app/model/webBook/BookList.kt index 6afadd419..e351ee3f3 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookList.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookList.kt @@ -14,9 +14,9 @@ import io.legado.app.model.analyzeRule.RuleData import io.legado.app.utils.HtmlFormatter import io.legado.app.utils.NetworkUtils import io.legado.app.utils.StringUtils.wordCountFormat -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ensureActive import splitties.init.appCtx +import kotlin.coroutines.coroutineContext /** * 获取书籍列表 @@ -24,8 +24,7 @@ import splitties.init.appCtx object BookList { @Throws(Exception::class) - fun analyzeBookList( - scope: CoroutineScope, + suspend fun analyzeBookList( bookSource: BookSource, ruleData: RuleData, analyzeUrl: AnalyzeUrl, @@ -46,11 +45,10 @@ object BookList { analyzeRule.setContent(body).setBaseUrl(baseUrl) analyzeRule.setRedirectUrl(baseUrl) bookSource.bookUrlPattern?.let { - scope.ensureActive() + coroutineContext.ensureActive() if (baseUrl.matches(it.toRegex())) { Debug.log(bookSource.bookSourceUrl, "≡链接为详情页") getInfoItem( - scope, bookSource, analyzeRule, analyzeUrl, @@ -81,11 +79,11 @@ object BookList { } Debug.log(bookSource.bookSourceUrl, "┌获取书籍列表") collections = analyzeRule.getElements(ruleList) - scope.ensureActive() + coroutineContext.ensureActive() if (collections.isEmpty() && bookSource.bookUrlPattern.isNullOrEmpty()) { Debug.log(bookSource.bookSourceUrl, "└列表为空,按详情页解析") getInfoItem( - scope, bookSource, analyzeRule, analyzeUrl, body, baseUrl, ruleData.getVariable() + bookSource, analyzeRule, analyzeUrl, body, baseUrl, ruleData.getVariable() )?.let { searchBook -> searchBook.infoHtml = body bookList.add(searchBook) @@ -102,7 +100,7 @@ object BookList { Debug.log(bookSource.bookSourceUrl, "└列表大小:${collections.size}") for ((index, item) in collections.withIndex()) { getSearchItem( - scope, bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(), + bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(), index == 0, ruleName = ruleName, ruleBookUrl = ruleBookUrl, @@ -127,8 +125,7 @@ object BookList { } @Throws(Exception::class) - private fun getInfoItem( - scope: CoroutineScope, + private suspend fun getInfoItem( bookSource: BookSource, analyzeRule: AnalyzeRule, analyzeUrl: AnalyzeUrl, @@ -144,7 +141,6 @@ object BookList { book.type = bookSource.bookSourceType analyzeRule.ruleData = book BookInfo.analyzeBookInfo( - scope, book, body, analyzeRule, @@ -160,8 +156,7 @@ object BookList { } @Throws(Exception::class) - private fun getSearchItem( - scope: CoroutineScope, + private suspend fun getSearchItem( bookSource: BookSource, analyzeRule: AnalyzeRule, item: Any, @@ -184,16 +179,16 @@ object BookList { searchBook.originOrder = bookSource.customOrder analyzeRule.ruleData = searchBook analyzeRule.setContent(item) - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取书名", log) searchBook.name = BookHelp.formatBookName(analyzeRule.getString(ruleName)) Debug.log(bookSource.bookSourceUrl, "└${searchBook.name}", log) if (searchBook.name.isNotEmpty()) { - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取作者", log) searchBook.author = BookHelp.formatBookAuthor(analyzeRule.getString(ruleAuthor)) Debug.log(bookSource.bookSourceUrl, "└${searchBook.author}", log) - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取分类", log) try { searchBook.kind = analyzeRule.getStringList(ruleKind)?.joinToString(",") @@ -201,7 +196,7 @@ object BookList { } catch (e: Exception) { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取字数", log) try { searchBook.wordCount = wordCountFormat(analyzeRule.getString(ruleWordCount)) @@ -209,7 +204,7 @@ object BookList { } catch (e: java.lang.Exception) { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取最新章节", log) try { searchBook.latestChapterTitle = analyzeRule.getString(ruleLastChapter) @@ -217,7 +212,7 @@ object BookList { } catch (e: java.lang.Exception) { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取简介", log) try { searchBook.intro = HtmlFormatter.format(analyzeRule.getString(ruleIntro)) @@ -225,7 +220,7 @@ object BookList { } catch (e: java.lang.Exception) { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取封面链接", log) try { analyzeRule.getString(ruleCoverUrl).let { @@ -237,7 +232,7 @@ object BookList { } catch (e: java.lang.Exception) { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log) } - scope.ensureActive() + coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取详情页链接", log) searchBook.bookUrl = analyzeRule.getString(ruleBookUrl, isUrl = true) if (searchBook.bookUrl.isEmpty()) { diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt index cd6f77cba..af2ef2a95 100644 --- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt +++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt @@ -29,12 +29,11 @@ object WebBook { context: CoroutineContext = Dispatchers.IO, ): Coroutine> { return Coroutine.async(scope, context) { - searchBookAwait(scope, bookSource, key, page) + searchBookAwait(bookSource, key, page) } } suspend fun searchBookAwait( - scope: CoroutineScope, bookSource: BookSource, key: String, page: Int? = 1, @@ -58,7 +57,6 @@ object WebBook { } } return BookList.analyzeBookList( - scope = scope, bookSource = bookSource, ruleData = ruleData, analyzeUrl = analyzeUrl, @@ -81,12 +79,11 @@ object WebBook { context: CoroutineContext = Dispatchers.IO, ): Coroutine> { return Coroutine.async(scope, context) { - exploreBookAwait(scope, bookSource, url, page) + exploreBookAwait(bookSource, url, page) } } suspend fun exploreBookAwait( - scope: CoroutineScope, bookSource: BookSource, url: String, page: Int? = 1, @@ -108,7 +105,6 @@ object WebBook { } } return BookList.analyzeBookList( - scope = scope, bookSource = bookSource, ruleData = ruleData, analyzeUrl = analyzeUrl, @@ -129,12 +125,11 @@ object WebBook { canReName: Boolean = true, ): Coroutine { return Coroutine.async(scope, context) { - getBookInfoAwait(scope, bookSource, book, canReName) + getBookInfoAwait(bookSource, book, canReName) } } suspend fun getBookInfoAwait( - scope: CoroutineScope, bookSource: BookSource, book: Book, canReName: Boolean = true, @@ -142,7 +137,6 @@ object WebBook { book.type = bookSource.bookSourceType if (!book.infoHtml.isNullOrEmpty()) { BookInfo.analyzeBookInfo( - scope = scope, bookSource = bookSource, book = book, baseUrl = book.bookUrl, @@ -166,7 +160,6 @@ object WebBook { } } BookInfo.analyzeBookInfo( - scope = scope, bookSource = bookSource, book = book, baseUrl = book.bookUrl, @@ -188,12 +181,11 @@ object WebBook { context: CoroutineContext = Dispatchers.IO ): Coroutine> { return Coroutine.async(scope, context) { - getChapterListAwait(scope, bookSource, book).getOrThrow() + getChapterListAwait(bookSource, book).getOrThrow() } } suspend fun getChapterListAwait( - scope: CoroutineScope, bookSource: BookSource, book: Book, ): Result> { @@ -201,7 +193,6 @@ object WebBook { return kotlin.runCatching { if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) { BookChapterList.analyzeChapterList( - scope = scope, bookSource = bookSource, book = book, baseUrl = book.tocUrl, @@ -224,7 +215,6 @@ object WebBook { } } BookChapterList.analyzeChapterList( - scope = scope, bookSource = bookSource, book = book, baseUrl = book.tocUrl, @@ -270,7 +260,6 @@ object WebBook { } return if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) { BookContent.analyzeContent( - scope = scope, bookSource = bookSource, book = book, bookChapter = bookChapter, @@ -300,7 +289,6 @@ object WebBook { } } BookContent.analyzeContent( - scope = scope, bookSource = bookSource, book = book, bookChapter = bookChapter, @@ -342,13 +330,13 @@ object WebBook { ): Result { return kotlin.runCatching { scope.isActive - searchBookAwait(scope, bookSource, name).firstOrNull { + searchBookAwait(bookSource, name).firstOrNull { it.name == name && it.author == author }?.let { searchBook -> scope.isActive var book = searchBook.toBook() if (book.tocUrl.isBlank()) { - book = getBookInfoAwait(scope, bookSource, book) + book = getBookInfoAwait(bookSource, book) } return@runCatching book } diff --git a/app/src/main/java/io/legado/app/service/CheckSourceService.kt b/app/src/main/java/io/legado/app/service/CheckSourceService.kt index bb92871fc..f131b5c19 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -24,8 +24,11 @@ import io.legado.app.utils.activityPendingIntent import io.legado.app.utils.postEvent import io.legado.app.utils.servicePendingIntent import io.legado.app.utils.toastOnUi -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.launch import org.mozilla.javascript.WrappedException import java.util.concurrent.Executors import kotlin.math.min @@ -139,7 +142,7 @@ class CheckSourceService : BaseService() { if (CheckSource.checkSearch) { if (!source.searchUrl.isNullOrBlank()) { source.removeGroup("搜索链接规则为空") - val searchBooks = WebBook.searchBookAwait(this, source, searchWord) + val searchBooks = WebBook.searchBookAwait(source, searchWord) if (searchBooks.isEmpty()) { source.addGroup("搜索失效") } else { @@ -164,7 +167,7 @@ class CheckSourceService : BaseService() { source.addGroup("发现规则为空") } else { source.removeGroup("发现规则为空") - val exploreBooks = WebBook.exploreBookAwait(this, source, url) + val exploreBooks = WebBook.exploreBookAwait(source, url) if (exploreBooks.isEmpty()) { source.addGroup("发现失效") } else { @@ -205,13 +208,13 @@ class CheckSourceService : BaseService() { //校验详情 if (CheckSource.checkInfo) { if (mBook.tocUrl.isBlank()) { - mBook = WebBook.getBookInfoAwait(this, source, mBook) + mBook = WebBook.getBookInfoAwait(source, mBook) } //校验目录 if (CheckSource.checkCategory && source.bookSourceType != BookType.file ) { - val toc = WebBook.getChapterListAwait(this, source, mBook).getOrThrow() + val toc = WebBook.getChapterListAwait(source, mBook).getOrThrow() val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url //校验正文 if (CheckSource.checkContent) { diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index ecd5bb2bf..2abcc602d 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -23,7 +23,6 @@ import io.legado.app.help.BookHelp import io.legado.app.help.ContentProcessor import io.legado.app.help.config.AppConfig import io.legado.app.utils.* -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.ensureActive import kotlinx.coroutines.sync.Mutex @@ -37,6 +36,7 @@ import java.io.File import java.io.FileOutputStream import java.nio.charset.Charset import java.util.concurrent.ConcurrentHashMap +import kotlin.coroutines.coroutineContext class CacheViewModel(application: Application) : BaseViewModel(application) { @@ -79,9 +79,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val uri = Uri.parse(path) val doc = DocumentFile.fromTreeUri(context, uri) ?: throw NoStackTraceException("获取导出文档失败") - export(this, doc, book) + export(doc, book) } else { - export(this, FileUtils.createFolderIfNotExist(path), book) + export(FileUtils.createFolderIfNotExist(path), book) } }.onError { exportProgress.remove(book.bookUrl) @@ -98,14 +98,14 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } @Suppress("BlockingMethodInNonBlockingContext") - private suspend fun export(scope: CoroutineScope, doc: DocumentFile, book: Book) { + private suspend fun export(doc: DocumentFile, book: Book) { val filename = "${getExportFileName(book)}.txt" DocumentUtils.delete(doc, filename) val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename) ?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹") val stringBuilder = StringBuilder() context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> - getAllContents(scope, book) { text, srcList -> + getAllContents(book) { text, srcList -> bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset))) stringBuilder.append(text) srcList?.forEach { @@ -128,12 +128,12 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } } - private suspend fun export(scope: CoroutineScope, file: File, book: Book) { + private suspend fun export(file: File, book: Book) { val filename = "${getExportFileName(book)}.txt" val bookPath = FileUtils.getPath(file, filename) val bookFile = FileUtils.createFileWithReplace(bookPath) val stringBuilder = StringBuilder() - getAllContents(scope, book) { text, srcList -> + getAllContents(book) { text, srcList -> bookFile.appendText(text, Charset.forName(AppConfig.exportCharset)) stringBuilder.append(text) srcList?.forEach { @@ -157,7 +157,6 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } private suspend fun getAllContents( - scope: CoroutineScope, book: Book, append: (text: String, srcList: ArrayList>?) -> Unit ) { @@ -173,7 +172,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { }" append(qy, null) appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> - scope.ensureActive() + coroutineContext.ensureActive() upAdapterLiveData.postValue(book.bookUrl) exportProgress[book.bookUrl] = index BookHelp.getContent(book, chapter).let { content -> @@ -227,9 +226,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val uri = Uri.parse(path) val doc = DocumentFile.fromTreeUri(context, uri) ?: throw NoStackTraceException("获取导出文档失败") - exportEpub(this, doc, book) + exportEpub(doc, book) } else { - exportEpub(this, FileUtils.createFolderIfNotExist(path), book) + exportEpub(FileUtils.createFolderIfNotExist(path), book) } }.onError { exportProgress.remove(book.bookUrl) @@ -246,7 +245,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } @Suppress("BlockingMethodInNonBlockingContext") - private suspend fun exportEpub(scope: CoroutineScope, doc: DocumentFile, book: Book) { + private suspend fun exportEpub(doc: DocumentFile, book: Book) { val filename = "${getExportFileName(book)}.epub" DocumentUtils.delete(doc, filename) val epubBook = EpubBook() @@ -259,7 +258,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val contentModel = setAssets(doc, book, epubBook) //设置正文 - setEpubContent(scope, contentModel, book, epubBook) + setEpubContent(contentModel, book, epubBook) DocumentUtils.createFileIfNotExist(doc, filename)?.let { bookDoc -> context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> EpubWriter().write(epubBook, bookOs) @@ -269,7 +268,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } - private suspend fun exportEpub(scope: CoroutineScope, file: File, book: Book) { + private suspend fun exportEpub(file: File, book: Book) { val filename = "${getExportFileName(book)}.epub" val epubBook = EpubBook() epubBook.version = "2.0" @@ -283,7 +282,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val bookPath = FileUtils.getPath(file, filename) val bookFile = FileUtils.createFileWithReplace(bookPath) //设置正文 - setEpubContent(scope, contentModel, book, epubBook) + setEpubContent(contentModel, book, epubBook) @Suppress("BlockingMethodInNonBlockingContext") EpubWriter().write(epubBook, FileOutputStream(bookFile)) } @@ -438,7 +437,6 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } private suspend fun setEpubContent( - scope: CoroutineScope, contentModel: String, book: Book, epubBook: EpubBook @@ -447,7 +445,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule() val contentProcessor = ContentProcessor.get(book.name, book.origin) appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> - scope.ensureActive() + coroutineContext.ensureActive() upAdapterLiveData.postValue(book.bookUrl) exportProgress[book.bookUrl] = index BookHelp.getContent(book, chapter).let { content -> diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt index 73e9fee69..bdd4c6922 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt @@ -21,7 +21,6 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.webBook.WebBook import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.toastOnUi -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher @@ -155,7 +154,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a } val source = bookSourceList[searchIndex] val task = Coroutine.async(scope = viewModelScope, context = searchPool!!) { - val resultBooks = WebBook.searchBookAwait(this, source, name) + val resultBooks = WebBook.searchBookAwait(source, name) resultBooks.forEach { searchBook -> if (searchBook.name == name) { if ((AppConfig.changeSourceCheckAuthor && searchBook.author.contains(author)) @@ -163,7 +162,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a ) { if (searchBook.latestChapterTitle.isNullOrEmpty()) { if (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) { - loadBookInfo(this, source, searchBook.toBook()) + loadBookInfo(source, searchBook.toBook()) } else { searchCallback?.searchSuccess(searchBook) } @@ -183,10 +182,10 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a tasks.add(task) } - private suspend fun loadBookInfo(scope: CoroutineScope, source: BookSource, book: Book) { - WebBook.getBookInfoAwait(scope, source, book) + private suspend fun loadBookInfo(source: BookSource, book: Book) { + WebBook.getBookInfoAwait(source, book) if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { - loadBookToc(scope, source, book) + loadBookToc(source, book) } else { //从详情页里获取最新章节 val searchBook = book.toSearchBook() @@ -194,8 +193,8 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a } } - private suspend fun loadBookToc(scope: CoroutineScope, source: BookSource, book: Book) { - val chapters = WebBook.getChapterListAwait(scope, source, book).getOrThrow() + private suspend fun loadBookToc(source: BookSource, book: Book) { + val chapters = WebBook.getChapterListAwait(source, book).getOrThrow() tocMap[book.bookUrl] = chapters book.latestChapterTitle = chapters.last().title val searchBook: SearchBook = book.toSearchBook() @@ -298,9 +297,9 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a val source = appDb.bookSourceDao.getBookSource(book.origin) ?: throw NoStackTraceException("书源不存在") if (book.tocUrl.isEmpty()) { - WebBook.getBookInfoAwait(this, source, book) + WebBook.getBookInfoAwait(source, book) } - val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow() + val toc = WebBook.getChapterListAwait(source, book).getOrThrow() Pair(toc, source) } } diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt index 89aa00611..ff89934c1 100644 --- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt @@ -51,7 +51,7 @@ class BookshelfManageViewModel(application: Application) : BaseViewModel(applica .onFailure { context.toastOnUi("获取书籍出错\n${it.localizedMessage}") }.getOrNull()?.let { newBook -> - WebBook.getChapterListAwait(this, source, newBook) + WebBook.getChapterListAwait(source, newBook) .onFailure { context.toastOnUi("获取目录出错\n${it.localizedMessage}") }.getOrNull()?.let { toc -> diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index 803bc9587..a29e9785d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -245,9 +245,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { sources.forEach { source -> WebBook.preciseSearchAwait(this, source, name, author).getOrNull()?.let { book -> if (book.tocUrl.isEmpty()) { - WebBook.getBookInfoAwait(this, source, book) + WebBook.getBookInfoAwait(source, book) } - val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow() + val toc = WebBook.getChapterListAwait(source, book).getOrThrow() changeTo(source, book, toc) return@execute } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt index 6161311b7..bc93b5311 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt @@ -160,7 +160,7 @@ class SearchContentActivity : binding.fbStop.visible() val searchResults = withContext(IO) { if (isLocalBook || viewModel.cacheChapterNames.contains(bookChapter.getFileName())) { - viewModel.searchChapter(this, query, bookChapter) + viewModel.searchChapter(query, bookChapter) } else { null } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt index ef6e87b17..96a78926c 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt @@ -10,10 +10,10 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.help.ContentProcessor import io.legado.app.help.config.AppConfig -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ensureActive import kotlinx.coroutines.withContext +import kotlin.coroutines.coroutineContext class SearchContentViewModel(application: Application) : BaseViewModel(application) { var bookUrl: String = "" @@ -38,7 +38,6 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati } suspend fun searchChapter( - scope: CoroutineScope, query: String, chapter: BookChapter? ): List { @@ -46,7 +45,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati if (chapter != null) { book?.let { book -> val chapterContent = BookHelp.getContent(book, chapter) - scope.ensureActive() + coroutineContext.ensureActive() if (chapterContent != null) { //先搜索没有启用净化的正文 withContext(Dispatchers.IO) { @@ -55,7 +54,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati 2 -> ChineseUtils.s2t(chapter.title) else -> chapter.title } - scope.ensureActive() + kotlin.coroutines.coroutineContext.ensureActive() mContent = contentProcessor!!.getContent( book, chapter, chapterContent, chineseConvert = true, @@ -63,9 +62,9 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati useReplace = false ).joinToString("") } - val positions = searchPosition(scope, query) + val positions = searchPosition(query) positions.forEachIndexed { index, position -> - scope.ensureActive() + coroutineContext.ensureActive() val construct = getResultAndQueryIndex(mContent, position, query) val result = SearchResult( resultCountWithinChapter = index, @@ -85,7 +84,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati return searchResultsWithinChapter } - private suspend fun searchPosition(scope: CoroutineScope, pattern: String): List { + private suspend fun searchPosition(pattern: String): List { val position: MutableList = mutableListOf() var index = mContent.indexOf(pattern) if (index >= 0) { @@ -95,7 +94,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati index = mContent.indexOf(pattern) } while (index >= 0) { - scope.ensureActive() + coroutineContext.ensureActive() position.add(index) index = mContent.indexOf(pattern, index + pattern.length) } diff --git a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt index 2d126a25b..c83f91280 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt @@ -123,9 +123,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) { AnalyzeRule(book, source).evalJS(preUpdateJs) } if (book.tocUrl.isBlank()) { - WebBook.getBookInfoAwait(this, source, book) + WebBook.getBookInfoAwait(source, book) } - val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow() + val toc = WebBook.getChapterListAwait(source, book).getOrThrow() if (book.bookUrl == bookUrl) { appDb.bookDao.update(book) } else {