diff --git a/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt b/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt index 5e98d7e18..01612b877 100644 --- a/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt +++ b/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt @@ -147,6 +147,7 @@ class Coroutine( } catch (e: Throwable) { e.printOnDebug() if (e is CancellationException && e !is TimeoutCancellationException) { + this@Coroutine.cancel() return@launch } val consume: Boolean = errorReturn?.value?.let { value -> 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 d132a6f18..291cb666a 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -135,6 +135,8 @@ object CacheBook { private val onDownloadSet = linkedSetOf() private val successDownloadSet = linkedSetOf() private val errorDownloadMap = hashMapOf() + private var isStopped = false + private var waitingRetry = false val waitCount get() = waitDownloadSet.size val onDownloadCount get() = onDownloadSet.size @@ -146,13 +148,20 @@ object CacheBook { return waitDownloadSet.size > 0 || onDownloadSet.size > 0 } + @Synchronized + fun isStop(): Boolean { + return isStopped || (!isRun() && !waitingRetry) + } + @Synchronized fun stop() { waitDownloadSet.clear() + isStopped = true } @Synchronized fun addDownload(start: Int, end: Int) { + isStopped = false for (i in start..end) { if (!onDownloadSet.contains(i)) { waitDownloadSet.add(i) @@ -168,13 +177,18 @@ object CacheBook { } @Synchronized - private fun onError(index: Int, error: Throwable, chapterTitle: String) { + private fun onPreError(index: Int, error: Throwable) { + waitingRetry = true if (error !is ConcurrentException) { errorDownloadMap[index] = (errorDownloadMap[index] ?: 0) + 1 } onDownloadSet.remove(index) + } + + @Synchronized + private fun onPostError(index: Int, error: Throwable, chapterTitle: String) { //重试3次 - if ((errorDownloadMap[index] ?: 0) < 3) { + if ((errorDownloadMap[index] ?: 0) < 3 && !isStopped) { waitDownloadSet.add(index) } else { AppLog.put( @@ -182,12 +196,19 @@ object CacheBook { error ) } + waitingRetry = false + } + + @Synchronized + private fun onError(index: Int, error: Throwable, chapterTitle: String) { + onPreError(index, error) + onPostError(index, error, chapterTitle) } @Synchronized private fun onCancel(index: Int) { onDownloadSet.remove(index) - waitDownloadSet.add(index) + if (!isStopped) waitDownloadSet.add(index) } @Synchronized @@ -234,9 +255,10 @@ object CacheBook { onSuccess(chapterIndex) downloadFinish(chapter, content) }.onError { + onPreError(chapterIndex, it) //出现错误等待一秒后重新加入待下载列表 delay(1000) - onError(chapterIndex, it, chapter.title) + onPostError(chapterIndex, it, chapter.title) downloadFinish(chapter, "获取正文失败\n${it.localizedMessage}") }.onCancel { onCancel(chapterIndex) diff --git a/app/src/main/java/io/legado/app/service/CacheBookService.kt b/app/src/main/java/io/legado/app/service/CacheBookService.kt index 3407c7034..d15d07c1d 100644 --- a/app/src/main/java/io/legado/app/service/CacheBookService.kt +++ b/app/src/main/java/io/legado/app/service/CacheBookService.kt @@ -74,6 +74,7 @@ class CacheBookService : BaseService() { override fun onDestroy() { isRun = false cachePool.close() + CacheBook.cacheBookMap.forEach { it.value.stop() } CacheBook.cacheBookMap.clear() super.onDestroy() postEvent(EventBus.UP_DOWNLOAD, "") @@ -84,6 +85,7 @@ class CacheBookService : BaseService() { execute { val cacheBook = CacheBook.getOrCreate(bookUrl) ?: return@execute cacheBook.addDownload(start, end) + postEvent(EventBus.UP_DOWNLOAD, "") upNotification(CacheBook.downloadSummary) if (downloadJob == null) { download() @@ -93,6 +95,11 @@ class CacheBookService : BaseService() { private fun removeDownload(bookUrl: String?) { CacheBook.cacheBookMap[bookUrl]?.stop() + postEvent(EventBus.UP_DOWNLOAD, "") + if (downloadJob == null && CacheBook.isRun) { + download() + return + } if (CacheBook.cacheBookMap.isEmpty()) { stopSelf() } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index 7264ee87f..26d3e2b90 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -237,6 +237,7 @@ class CacheActivity : VMBaseActivity() observeEvent(EventBus.SAVE_CONTENT) { adapter.cacheChapters[it.bookUrl]?.add(it.url) } + postEventDelay(EventBus.UP_DOWNLOAD, "", 100) } override fun export(position: Int) { diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt index 4a4e601c4..10d31a4cb 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt @@ -67,7 +67,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : ivDownload.setOnClickListener { getItem(holder.layoutPosition)?.let { book -> CacheBook.cacheBookMap[book.bookUrl]?.let { - if (it.isRun()) { + if (!it.isStop()) { CacheBook.remove(context, book.bookUrl) } else { CacheBook.start(context, book, 0, book.totalChapterNum) @@ -89,7 +89,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : } else { iv.visible() CacheBook.cacheBookMap[book.bookUrl]?.let { - if (it.isRun()) { + if (!it.isStop()) { iv.setImageResource(R.drawable.ic_stop_black_24dp) } else { iv.setImageResource(R.drawable.ic_play_24dp) 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 69dea8cfe..ef0dcab63 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 @@ -186,13 +186,14 @@ class MainViewModel(application: Application) : BaseViewModel(application) { private fun cacheBook() { cacheBookJob?.cancel() cacheBookJob = viewModelScope.launch(upTocPool) { - while (isActive) { - if (CacheBookService.isRun) { - cacheBookJob?.cancel() - cacheBookJob = null - return@launch + launch { + while (isActive) { + postEvent(EventBus.UP_DOWNLOAD, "") + delay(1000) } - if (!CacheBook.isRun) { + } + while (isActive) { + if (CacheBookService.isRun || !CacheBook.isRun) { cacheBookJob?.cancel() cacheBookJob = null return@launch