diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index 50be03c59..a1ee39e05 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -47,7 +47,6 @@ import io.legado.app.utils.toStringArray import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.async -import kotlinx.coroutines.ensureActive import kotlinx.coroutines.runBlocking import okio.use import org.jsoup.Connection @@ -83,11 +82,11 @@ interface JsExtensions : JsEncodeUtils { fun getSource(): BaseSource? + private val rhinoContext: RhinoContext + get() = Context.getCurrentContext() as RhinoContext + private val context: CoroutineContext - get() { - val rhinoContext = Context.getCurrentContext() as RhinoContext - return rhinoContext.coroutineContext ?: EmptyCoroutineContext - } + get() = rhinoContext.coroutineContext ?: EmptyCoroutineContext /** * 访问网络,返回String @@ -361,7 +360,7 @@ interface JsExtensions : JsEncodeUtils { } else headers val rateLimiter = ConcurrentRateLimiter(getSource()) val response = rateLimiter.withLimitBlocking { - context.ensureActive() + rhinoContext.ensureActive() Jsoup.connect(urlStr) .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory) .ignoreContentType(true) @@ -382,7 +381,7 @@ interface JsExtensions : JsEncodeUtils { } else headers val rateLimiter = ConcurrentRateLimiter(getSource()) val response = rateLimiter.withLimitBlocking { - context.ensureActive() + rhinoContext.ensureActive() Jsoup.connect(urlStr) .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory) .ignoreContentType(true) @@ -403,7 +402,7 @@ interface JsExtensions : JsEncodeUtils { } else headers val rateLimiter = ConcurrentRateLimiter(getSource()) val response = rateLimiter.withLimitBlocking { - context.ensureActive() + rhinoContext.ensureActive() Jsoup.connect(urlStr) .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory) .ignoreContentType(true) @@ -897,7 +896,8 @@ interface JsExtensions : JsEncodeUtils { s ?: return null val matcher = AppPattern.titleNumPattern.matcher(s) if (matcher.find()) { - return "${matcher.group(1)}${StringUtils.stringToInt(matcher.group(2))}${matcher.group(3)}" + val intStr = StringUtils.stringToInt(matcher.group(2)) + return "${matcher.group(1)}${intStr}${matcher.group(3)}" } return s } 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 9b36b760c..9549e7951 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.delay +import kotlinx.coroutines.sync.Semaphore import java.util.concurrent.ConcurrentHashMap import kotlin.coroutines.CoroutineContext @@ -338,6 +339,7 @@ object CacheBook { fun download( scope: CoroutineScope, chapter: BookChapter, + semaphore: Semaphore?, resetPageOffset: Boolean = false ) { if (onDownloadSet.contains(chapter.index)) { diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index e80c71f48..07cba50b1 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.withContext import splitties.init.appCtx import kotlin.math.max @@ -92,6 +93,7 @@ object ReadBook : CoroutineScope by MainScope() { val downloadFailChapters = hashMapOf() var contentProcessor: ContentProcessor? = null val downloadScope = CoroutineScope(SupervisorJob() + IO) + val preDownloadSemaphore = Semaphore(2) val executor = globalExecutor //暂时保存跳转前进度 @@ -492,6 +494,8 @@ object ReadBook : CoroutineScope by MainScope() { val isScroll inline get() = pageAnim() == scrollPageAnim + val contentLoadFinish get() = curTextChapter != null || msg != null + /** * chapterOnDur: 0为当前页,1为下一页,-1为上一页 */ @@ -612,10 +616,10 @@ object ReadBook : CoroutineScope by MainScope() { downloadedChapters.add(chapter.index) } else { delay(1000) - download(downloadScope, chapter, false) + download(downloadScope, chapter, false, preDownloadSemaphore) } } ?: removeLoading(index) - } catch (e: Exception) { + } catch (_: Exception) { removeLoading(index) } } @@ -628,12 +632,13 @@ object ReadBook : CoroutineScope by MainScope() { scope: CoroutineScope, chapter: BookChapter, resetPageOffset: Boolean, + semaphore: Semaphore? = null, success: (() -> Unit)? = null ) { val book = book ?: return removeLoading(chapter.index) val bookSource = bookSource if (bookSource != null) { - CacheBook.getOrCreate(bookSource, book).download(scope, chapter) + CacheBook.getOrCreate(bookSource, book).download(scope, chapter, semaphore) } else { val msg = if (book.isLocal) "无内容" else "没有书源" contentLoadFinish( @@ -905,6 +910,13 @@ object ReadBook : CoroutineScope by MainScope() { } } + fun cancelPreDownloadTask() { + if (contentLoadFinish) { + preDownloadTask?.cancel() + downloadScope.coroutineContext.cancelChildren() + } + } + /** * 注册回调 */ 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 dd565ae95..3267a4c24 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 @@ -20,6 +20,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.isActive +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext @@ -282,9 +284,14 @@ object WebBook { context: CoroutineContext = Dispatchers.IO, start: CoroutineStart = CoroutineStart.DEFAULT, executeContext: CoroutineContext = Dispatchers.Main, + semaphore: Semaphore? = null, ): Coroutine { return Coroutine.async(scope, context, start = start, executeContext = executeContext) { - getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave) + semaphore?.withPermit { + getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave) + } ?: run { + getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave) + } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index feb34948a..8b8b445aa 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -312,6 +312,8 @@ class ReadBookActivity : BaseReadBookActivity(), upSystemUiVisibility() if (hasFocus) { binding.readMenu.upBrightnessState() + } else if (!menuLayoutIsVisible) { + ReadBook.cancelPreDownloadTask() } } @@ -356,6 +358,7 @@ class ReadBookActivity : BaseReadBookActivity(), autoPageStop() backupJob?.cancel() ReadBook.saveRead() + ReadBook.cancelPreDownloadTask() unregisterReceiver(timeBatteryReceiver) upSystemUiVisibility() if (!BuildConfig.DEBUG) {