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 ada00455d..1294454de 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -29,6 +29,8 @@ import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.delay import kotlinx.coroutines.launch import splitties.init.appCtx +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors import kotlin.math.min @@ -63,6 +65,7 @@ object ReadBook : CoroutineScope by MainScope() { val downloadFailChapters = hashMapOf() var contentProcessor: ContentProcessor? = null val downloadScope = CoroutineScope(SupervisorJob() + IO) + val executor: ExecutorService = Executors.newSingleThreadExecutor() //暂时保存跳转前进度 fun saveCurrentBookProcess() { @@ -158,10 +161,10 @@ object ReadBook : CoroutineScope by MainScope() { } fun upReadTime() { - if (!AppConfig.enableReadRecord) { - return - } - Coroutine.async(executeContext = IO) { + executor.execute { + if (!AppConfig.enableReadRecord) { + return@execute + } readRecord.readTime = readRecord.readTime + System.currentTimeMillis() - readStartTime readStartTime = System.currentTimeMillis() readRecord.lastRead = System.currentTimeMillis() @@ -536,8 +539,8 @@ object ReadBook : CoroutineScope by MainScope() { } fun saveRead(pageChanged: Boolean = false) { - Coroutine.async(executeContext = IO) { - val book = book ?: return@async + executor.execute { + val book = book ?: return@execute book.lastCheckCount = 0 book.durChapterTime = System.currentTimeMillis() val chapterChanged = book.durChapterIndex != durChapterIndex @@ -560,26 +563,29 @@ object ReadBook : CoroutineScope by MainScope() { */ private fun preDownload() { if (book?.isLocal == true) return - if (AppConfig.preDownloadNum < 2) { - return - } - preDownloadTask?.cancel() - preDownloadTask = Coroutine.async(executeContext = IO) { - //预下载 - launch { - val maxChapterIndex = min(durChapterIndex + AppConfig.preDownloadNum, chapterSize) - for (i in durChapterIndex.plus(2)..maxChapterIndex) { - if (downloadedChapters.contains(i)) continue - if ((downloadFailChapters[i] ?: 0) >= 3) continue - downloadIndex(i) - } + executor.execute { + if (AppConfig.preDownloadNum < 2) { + return@execute } - launch { - val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum) - for (i in durChapterIndex.minus(2) downTo minChapterIndex) { - if (downloadedChapters.contains(i)) continue - if ((downloadFailChapters[i] ?: 0) >= 3) continue - downloadIndex(i) + preDownloadTask?.cancel() + preDownloadTask = Coroutine.async(executeContext = IO) { + //预下载 + launch { + val maxChapterIndex = + min(durChapterIndex + AppConfig.preDownloadNum, chapterSize) + for (i in durChapterIndex.plus(2)..maxChapterIndex) { + if (downloadedChapters.contains(i)) continue + if ((downloadFailChapters[i] ?: 0) >= 3) continue + downloadIndex(i) + } + } + launch { + val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum) + for (i in durChapterIndex.minus(2) downTo minChapterIndex) { + if (downloadedChapters.contains(i)) continue + if ((downloadFailChapters[i] ?: 0) >= 3) continue + downloadIndex(i) + } } } } diff --git a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt index 7070861be..a8ef1f579 100644 --- a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt @@ -91,7 +91,7 @@ class HttpReadAloudService : BaseReadAloudService(), playIndexJob?.cancel() } - private fun playNext() { + private fun updateNextPos() { readAloudNumber += contentList[nowSpeak].length + 1 - paragraphStartPos paragraphStartPos = 0 if (nowSpeak < contentList.lastIndex) { @@ -355,14 +355,14 @@ class HttpReadAloudService : BaseReadAloudService(), Player.STATE_ENDED -> { // 结束 playErrorNo = 0 - playNext() + updateNextPos() } } } override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) return - playNext() + updateNextPos() upPlayPos() } @@ -375,7 +375,8 @@ class HttpReadAloudService : BaseReadAloudService(), AppLog.put("朗读连续5次错误, 最后一次错误代码(${error.localizedMessage})", error) ReadAloud.pause(this) } else { - playNext() + updateNextPos() + exoPlayer.seekToNextMediaItem() } } 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 254b3d720..28623edb5 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 @@ -191,7 +191,6 @@ class ReadBookActivity : BaseReadBookActivity(), } private var menu: Menu? = null private var backupJob: Job? = null - private var keepScreenJon: Job? = null private var tts: TTS? = null val textActionMenu: TextActionMenu by lazy { TextActionMenu(this, this) @@ -221,7 +220,7 @@ class ReadBookActivity : BaseReadBookActivity(), private var reloadContent = false private val handler by lazy { buildMainHandler() } private val screenOffRunnable by lazy { Runnable { keepScreenOn(false) } } - private val executor = IO.asExecutor() + private val executor = ReadBook.executor //恢复跳转前进度对话框的交互结果 private var confirmRestoreProcess: Boolean? = null diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt index cf472bdf4..d78440c88 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt @@ -380,6 +380,8 @@ object ChapterProvider { textLine.addColumn( ImageColumn(start = x + start, end = x + end, src = src) ) + calcTextLinePosition(textPages, textLine, stringBuilder.length) + stringBuilder.append(" ") // 确保翻页时索引计算正确 textPages.last().addLine(textLine) } return absStartX to durY + textHeight * paragraphSpacing / 10f @@ -519,24 +521,11 @@ object ChapterProvider { if (doublePage) { textLine.isLeftLine = absStartX < viewWidth / 2 } - val sbLength = stringBuilder.length + calcTextLinePosition(textPages, textLine, stringBuilder.length) stringBuilder.append(lineText) if (textLine.isParagraphEnd) { stringBuilder.append("\n") } - val lastLine = textPages.last().lines.lastOrNull { it.paragraphNum > 0 } - ?: textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull { it.paragraphNum > 0 } - val paragraphNum = when { - lastLine == null -> 1 - lastLine.isParagraphEnd -> lastLine.paragraphNum + 1 - else -> lastLine.paragraphNum - } - textLine.paragraphNum = paragraphNum - textLine.chapterPosition = - (textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull()?.run { - chapterPosition + charSize + if (isParagraphEnd) 1 else 0 - } ?: 0) + sbLength - textLine.pagePosition = sbLength textLine.upTopBottom(durY, textHeight, fontMetrics) val textPage = textPages.last() textPage.addLine(textLine) @@ -549,6 +538,26 @@ object ChapterProvider { return Pair(absStartX, durY) } + private fun calcTextLinePosition( + textPages: ArrayList, + textLine: TextLine, + sbLength: Int + ) { + val lastLine = textPages.last().lines.lastOrNull { it.paragraphNum > 0 } + ?: textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull { it.paragraphNum > 0 } + val paragraphNum = when { + lastLine == null -> 1 + lastLine.isParagraphEnd -> lastLine.paragraphNum + 1 + else -> lastLine.paragraphNum + } + textLine.paragraphNum = paragraphNum + textLine.chapterPosition = + (textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull()?.run { + chapterPosition + charSize + if (isParagraphEnd) 1 else 0 + } ?: 0) + sbLength + textLine.pagePosition = sbLength + } + /** * 有缩进,两端对齐 */