下载优化
This commit is contained in:
4 files changed
+47
-19
No files matched your search
@@ -78,7 +78,7 @@ object CacheBook {
|
|||||||
}
|
}
|
||||||
var emitted = false
|
var emitted = false
|
||||||
taskMap.forEach { (_, model) ->
|
taskMap.forEach { (_, model) ->
|
||||||
if (model.hasRunnableDownloads()) {
|
if (model.hasLaunchableChapters()) {
|
||||||
emit(model)
|
emit(model)
|
||||||
emitted = true
|
emitted = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,6 +153,16 @@ class CacheBookModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 有可启动的下载任务(队列中有待下载章节或正在加载目录)。
|
||||||
|
* 与 [hasRunnableDownloads] 不同,不包含已在执行中的任务。
|
||||||
|
* 用于判断是否需要向下载循环 emit 模型,避免无新章节可取时的高频空转。
|
||||||
|
*/
|
||||||
|
@Synchronized
|
||||||
|
fun hasLaunchableChapters(): Boolean {
|
||||||
|
return !isPaused && (queue.waitingCount() > 0 || isLoading)
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun diagnostics(): Diagnostics {
|
fun diagnostics(): Diagnostics {
|
||||||
return Diagnostics(
|
return Diagnostics(
|
||||||
@@ -579,7 +589,7 @@ class CacheBookModel(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repository.downloadContentTask(
|
val task = repository.downloadContentTask(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
bookSource = bookSource,
|
bookSource = bookSource,
|
||||||
book = book,
|
book = book,
|
||||||
@@ -604,8 +614,13 @@ class CacheBookModel(
|
|||||||
onCancel(chapter.index, requeue = false)
|
onCancel(chapter.index, requeue = false)
|
||||||
downloadFinish(chapter, "download canceled", resetPageOffset, true)
|
downloadFinish(chapter, "download canceled", resetPageOffset, true)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
|
chapterTasks.remove(chapter.index)
|
||||||
host.onTaskQueuesChanged(book.bookUrl)
|
host.onTaskQueuesChanged(book.bookUrl)
|
||||||
}.start()
|
}
|
||||||
|
task.start()
|
||||||
|
synchronized(this) {
|
||||||
|
chapterTasks[chapter.index] = task
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,21 @@ class CacheDownloadQueue {
|
|||||||
val indexCount = indices.count {
|
val indexCount = indices.count {
|
||||||
!emittedIndices.contains(it) && !removedIndices.contains(it)
|
!emittedIndices.contains(it) && !removedIndices.contains(it)
|
||||||
}
|
}
|
||||||
val rangeCount = ranges.sumOf { it.remainingCount(emittedIndices, removedIndices) }
|
val rangeCount = if (ranges.size <= 1) {
|
||||||
|
ranges.sumOf { it.remainingCount(emittedIndices, removedIndices) }
|
||||||
|
} else {
|
||||||
|
val seen = mutableSetOf<Int>()
|
||||||
|
ranges.forEach { cursor ->
|
||||||
|
var i = cursor.next
|
||||||
|
while (i <= cursor.end) {
|
||||||
|
if (!emittedIndices.contains(i) && !removedIndices.contains(i)) {
|
||||||
|
seen.add(i)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seen.size
|
||||||
|
}
|
||||||
return indexCount + rangeCount
|
return indexCount + rangeCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import io.legado.app.constant.NotificationId
|
|||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.help.book.update
|
import io.legado.app.help.book.update
|
||||||
import io.legado.app.model.CacheBook
|
import io.legado.app.model.CacheBook
|
||||||
|
import io.legado.app.model.CacheBookModel
|
||||||
import io.legado.app.model.cache.CacheDownloadAdmissionQueue
|
import io.legado.app.model.cache.CacheDownloadAdmissionQueue
|
||||||
import io.legado.app.model.cache.CacheDownloadRequest
|
import io.legado.app.model.cache.CacheDownloadRequest
|
||||||
import io.legado.app.model.cache.CacheDownloadSource
|
import io.legado.app.model.cache.CacheDownloadSource
|
||||||
@@ -24,11 +25,11 @@ import io.legado.app.utils.activityPendingIntent
|
|||||||
import io.legado.app.utils.servicePendingIntent
|
import io.legado.app.utils.servicePendingIntent
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.currentCoroutineContext
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -310,10 +311,10 @@ class CacheBookService : BaseService() {
|
|||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
WebBook.getBookInfoAwait(cacheBook.bookSource, book)
|
WebBook.getBookInfoAwait(cacheBook.bookSource, book)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
removeDownload(request.bookUrl)
|
|
||||||
markBookAdmissionFailed(
|
markBookAdmissionFailed(
|
||||||
request.bookUrl,
|
request.bookUrl,
|
||||||
getString(R.string.error_get_book_info)
|
getString(R.string.error_get_book_info),
|
||||||
|
model = cacheBook,
|
||||||
)
|
)
|
||||||
AppLog.put(
|
AppLog.put(
|
||||||
"《$name》目录为空且加载详情页失败\n${it.localizedMessage}",
|
"《$name》目录为空且加载详情页失败\n${it.localizedMessage}",
|
||||||
@@ -333,10 +334,10 @@ class CacheBookService : BaseService() {
|
|||||||
book.totalChapterNum = 0
|
book.totalChapterNum = 0
|
||||||
book.update()
|
book.update()
|
||||||
}
|
}
|
||||||
removeDownload(request.bookUrl)
|
|
||||||
markBookAdmissionFailed(
|
markBookAdmissionFailed(
|
||||||
request.bookUrl,
|
request.bookUrl,
|
||||||
getString(R.string.error_get_chapter_list)
|
getString(R.string.error_get_chapter_list),
|
||||||
|
model = cacheBook,
|
||||||
)
|
)
|
||||||
AppLog.put(
|
AppLog.put(
|
||||||
"《$name》目录为空且加载目录失败\n${it.localizedMessage}",
|
"《$name》目录为空且加载目录失败\n${it.localizedMessage}",
|
||||||
@@ -408,8 +409,15 @@ class CacheBookService : BaseService() {
|
|||||||
return removedQueued || removedAdmission || removedActive
|
return removedQueued || removedAdmission || removedActive
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun markBookAdmissionFailed(bookUrl: String, message: String) {
|
private fun markBookAdmissionFailed(
|
||||||
|
bookUrl: String,
|
||||||
|
message: String,
|
||||||
|
model: CacheBookModel? = null,
|
||||||
|
) {
|
||||||
removeQueuedBook(bookUrl)
|
removeQueuedBook(bookUrl)
|
||||||
|
if (model != null) {
|
||||||
|
CacheBook.removeModelFromService(bookUrl, model)
|
||||||
|
}
|
||||||
CacheBook.markBookFailed(bookUrl, message)
|
CacheBook.markBookFailed(bookUrl, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,15 +484,6 @@ class CacheBookService : BaseService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun removeDownload(bookUrl: String?) {
|
|
||||||
CacheBook.cacheBookMap[bookUrl]?.stop()
|
|
||||||
if (CacheBook.isRun) {
|
|
||||||
ensureDownloadJob()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
stopIfIdle()
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun runDownloadLoop() {
|
private suspend fun runDownloadLoop() {
|
||||||
try {
|
try {
|
||||||
var idleSince = -1L
|
var idleSince = -1L
|
||||||
|
|||||||
Reference in new issue
Block a user